Класс Functor, выполняющий работу в конструкторе - PullRequest
0 голосов
/ 07 марта 2009

Я использую шаблоны 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 */
 }

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

Ответы [ 5 ]

2 голосов
/ 07 марта 2009

Есть ли недостатки?

  • Ctors не возвращают никакого полезного значения - не могут использоваться в цепочечных вызовах (например, foo (bar ()).
  • Они могут бросить.
  • Точка зрения проектирования - ctors - это функции создания объектов, которые на самом деле не должны быть рабочими лошадками.
1 голос
/ 07 марта 2009

Благодаря производительности, код, продемонстрированный с, полностью оптимизирован как с VC, так и с GCC. Тем не менее, лучшей стратегией часто является использование функтора в качестве параметра, так что вы получаете гораздо больше гибкости и идентичных характеристик производительности.

1 голос
/ 07 марта 2009
  1. Компиляторы на самом деле встроили пустой конструктор Operation (по крайней мере, gcc в подобных ситуациях делает, кроме случаев, когда вы выключили оптимизацию)
  2. Недостаток выполнения всего в конструкторе состоит в том, что вы не можете создать функтор с некоторым внутренним состоянием таким образом - например. функтор для подсчета количества элементов, удовлетворяющих предикату. Кроме того, использование метода реального объекта в качестве функтора позволяет сохранить его экземпляр для последующего выполнения, чего вы не можете сделать с помощью конструкторского подхода.
0 голосов
/ 08 марта 2009

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

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

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

0 голосов
/ 07 марта 2009

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

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

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

my_algorithm(foo, bar, MyOperation())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...