Класс-функтор, выполняющий работу в конструкторе

StackOverflow https://stackoverflow.com/questions/622048

Вопрос

Я использую шаблоны C++ для передачи функторов стратегии, чтобы изменить поведение моей функции.Он работает нормально.Функтор, который я передаю, представляет собой класс без сохранения состояния, не имеющий хранилища, и он просто перегружает оператор () классическим функторным способом.

template <typename Operation> int foo(int a) 
{
int b=Operation()(a);
/* use b here, etc */
}

Я делаю это часто, и это хорошо работает, и часто я создаю шаблоны с 6 или 7 переданными шаблонными функторами!

Однако меня беспокоит как элегантность кода, так и эффективность.Функтор не имеет состояния, поэтому я предполагаю, что конструктор Operation() бесплатен, а оценка функтора так же эффективна, как и встроенная функция, но, как и у всех программистов C++, у меня всегда есть некоторые мучительные сомнения.

Мой второй вопрос: могу ли я использовать альтернативный функторный подход.тот, который не переопределяет оператор (), но делает все в конструкторе как побочный эффект!Что-то вроде:

struct Operation {
  Operation(int a, int &b) { b=a*a; }
};
template <typename Operation> int foo(int a) 
 {
   int b;
   Operation(a,b);
    /* use b here, etc */
 }

Я никогда не видел, чтобы кто-нибудь использовал конструктор в качестве «работы» функтора, но кажется, что он должен работать.Есть ли преимущество?Какой-нибудь недостаток?Мне нравится удаление странной двойной скобки «Operator()(a)» , но, скорее всего, это просто эстетика.

Это было полезно?

Решение

Какой-нибудь недостаток?

  • Векторы не возвращают никакого полезного значения — их нельзя использовать в цепочках вызовов (например,фу(бар()).
  • Они могут бросить.
  • С точки зрения дизайна: векторы — это функции создания объектов, которые на самом деле не предназначены для использования в качестве рабочих лошадок.

Другие советы

<Ол>
  • Компиляторы фактически вставляют пустой конструктор Operation (по крайней мере, gcc в подобных ситуациях делает, кроме случаев, когда вы выключили оптимизацию)
  • Недостаток выполнения всего в конструкторе состоит в том, что вы не можете создать функтор с некоторым внутренним состоянием таким образом - например. функтор для подсчета количества элементов, удовлетворяющих предикату. Кроме того, использование метода реального объекта в качестве функтора позволяет сохранить его экземпляр для последующего выполнения, чего нельзя сделать с помощью конструкторского подхода.
  • Благодаря производительности, код, продемонстрированный с, был полностью оптимизирован как для VC, так и для GCC. Тем не менее, лучшей стратегией часто является использование функтора в качестве параметра, чтобы получить гораздо большую гибкость и идентичные характеристики производительности.

    Я бы рекомендовал определить функтор, который работает с STL-контейнерами, т. е. они должны реализовывать operator (). (Следовать API языка, который вы используете, всегда хорошая идея.)

    Это позволяет вашим алгоритмам быть очень общими (передавать функции, функторы, stl-bind, boost :: function, boost :: bind, boost :: lambda, ...), что обычно и требуется.

    Таким образом, вам не нужно указывать тип функтора в качестве параметра шаблона, просто создайте экземпляр и передайте его:

    my_algorithm(foo, bar, MyOperation())
    

    Нет смысла реализовывать конструктор в другом классе.
    Все, что вы делаете, это нарушаете инкапсуляцию и настраиваете свой класс на злоупотребления.

    Конструктор должен инициализировать объект в хорошем состоянии, как определено классом. Вы позволяете другому объекту инициализировать ваш класс. Какие у вас гарантии, что этот шаблонный класс знает, как правильно инициализировать ваш класс? Пользователь вашего класса может предоставить любой объект, который может связываться с внутренним состоянием вашего объекта способами, не предназначенными.

    Класс должен быть автономным и инициализироваться в хорошем состоянии. Похоже, что вы играете с шаблонами, просто чтобы посмотреть, на что они способны.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top