Универсальный класс Functor в C ++ - PullRequest
2 голосов
/ 19 февраля 2012

Я пытался построить поверх потока здесь: Список аргументов шаблона переменной длины? иметь класс Functor по умолчанию, это только академический интерес. Моя цель - создать общий класс Fucntor: учитывая имя класса, имя метода и типы аргументов (переменной длины), он создает класс с методом operator (), который принимает переменное число аргументов типа, указанного в аргументах шаблона берет указатель и применяет данный метод. Представьте себе класс таким образом:

class MyClass
{
 public:
   float Fraction( float n, int m)
   {
       return n/m;
   }
   int Increment(int n)
   {
       return n+1;
   }
} ;

И шаблонизированный класс функторов, который можно использовать в любой функции следующим образом:

int k = FunctorClass<MyClass, Increment, int, int /*return type*/> (3);
assert(k == 4);
float l = FunctorClass<MyClass, Fraction,  float, int, float, /*return type*/> (4,3);
assert(l == (4/3));

Можно ли построить такой класс функторов? Sidenote: не могу использовать шаблоны Variadic (сборка в VS2010, нет ... аргументов шаблона) Спасибо за помощь

Ответы [ 2 ]

2 голосов
/ 19 февраля 2012

Это, безусловно, выполнимо, например, Boost bind () использует этот подход под капотом. Однако, без использования вариаций вы не получите полной общности, потому что вы будете ограничены фиксированным числом аргументов шаблона и вам нужно будет вводить реализацию для каждого разного числа аргументов, которые вы хотите поддерживать. Кроме того, без ссылок rvalue вы не получите идеальную пересылку.

Тем не менее, способ, которым вы пытаетесь использовать его, не сработает: при указании функций-членов вы не можете просто назвать их. Вам необходимо получить правильную точку функции члена, например, используя &MyClass::Increment и &MyClass::Fraction. Если функция-член перегружена, вам необходимо устранить ее неоднозначность.

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

* * 1010
0 голосов
/ 14 марта 2012

Я не уверен, что вам понадобятся вариады для этого. Рассмотрим следующий интерфейс ...

template < typename RETURN_TYPE >
class iFunctor abstract {

    public:

        virtual RETURN_TYPE operator () ( void ) = 0;

};

Абстрактные интерфейсы не являются полноценными классами, они могут содержать частичную реализацию, такую ​​как сигнатуры функций и некоторые члены данных. С помощью шаблона вы можете обобщить тип возвращаемого значения. Но как насчет списка аргументов, который вы говорите?

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

template < typename TYPE >
class ConcreteFunctor_add : public iFunctor < TYPE > {

    private:

       int A;
       int B;

    public:

       explicit ConcreteFunctor_add ( const int &a, const int &b ) : A(a), B(b) {};

       TYPE operator () ( void ) { return ( A + B ); };

};

Вы имеете дело со списком аргументов в каждом конкретном случае через конструктор.

Для явного конструктора требуется список аргументов при объявлении, поэтому вы получите список переменных здесь. Так на практике ...

ConcreteFunctor_add < int > addInteger ( 10, 10 );
addInteger();

... и ты будешь крут.

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