2009-05-05 2 views
0

У меня есть класс, который использует функторы как единицы работы. Он принимает ссылку на функтор в методе Run(). Чтобы разрешить этот класс работать на любом функторе, все эти функторы должны наследоваться от моего базового класса функтора, который выглядит следующим образом:Производный функтор с любым типом возвращаемого значения и любыми параметрами

class baseFunctor{ 

public: 
    virtual void operator()()=0; 
    virtual baseFunctor Clone()=0; 
}; 

Это работает, однако, очевидно, что ограничивает эти функторы к наличию операторного метода, который возвращает недействительным и не принимает никаких параметров. Мне нужно иметь возможность принять функтор в моем классе, который может принимать любые параметры и возвращать что-либо. Очевидно, что он способен, но я не могу найти способ сделать это. Я рассмотрел использование шаблонов, множественное наследование, но я все время сдерживаюсь из-за того, что класс, который должен запускать этот функтор, должен иметь возможность принимать любой тип, поэтому он будет принимать тип базового класса и поэтому не будет знать фактический тип функтора.

Любые предложения о том, что можно было бы оценить по достоинству.

ответ

2

Как класс, который вызывает функтор знать, какие параметры, чтобы обеспечить, и что делать с возвращаемым значением, если таковые имеются?

0

Почему вы хотите вернуть функтор? Вы также сохраняете какое-то состояние? Более подробная информация будет оценена, поскольку не совсем понятно, что именно вы хотите сделать.

Если вы планируете использовать наследование, просмотрите Covariant Return Types (и Virtual Constructor idiom).

Теперь, для мяса проблемы: проблема действительно не в том, чтобы проходить в функторе, а с применением функтора. Вы можете взглянуть на boost::lambda и boost::parameter.

0

Я думаю, что вам нужен аргумент с многоточием, например varargs для C++.

1

Если вы открыты для использования библиотеки Boost (www.boost.org), вы можете найти Boot.Bind и Boost.Function, представляющие особый интерес. Я использовал их в прошлом, чтобы добиться чего-то очень похожего на то, что вы обсуждаете.

Если вы используете Boost.Bind, вы можете выполнить currying на функторах для учета различий между количеством аргументов, ожидаемых функтором, и количеством аргументов, которые ожидает метод Run (т. Е. Ноль). Код, создающий функтор, должен будет связывать любые аргументы с определенными значениями и тем самым создавать функтор нулевого аргумента, который можно передать в Run().

М.В.

0

Возможно, функция std :: tr1 :: интересна для вас?

1

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

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

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

+0

Хорошо, это имеет смысл. Основной класс, создающий класс и передающий ему функтор, знает, какой тип является функтором, его класс, который получает функтор, который этого не делает, и просто вызывает метод operator(). Я загляну в шаблон посетителя, спасибо за информацию. –

1

Я согласен с Нилом.Ваш основной класс должен знать, какие параметры должны пройти и какое возвращаемое значение ожидать от этих функторов. Можете ли вы просто набросать «функтор» на соответствующий класс, который поддерживает функцию с необходимыми аргументами и возвращаемым значением?

class baseFunctor 
{ 
}; 

class functor1x2: public baseFunctor 
{ 
public: 
    virtual void* execute(void*, void*); 

} 

class MainClass 
{ 
public: 
    void Execute(baseFunctor* ipFunctor) 
    { 
     functor1x2* lpFunctor1x2 = dynamic_cast<functor1x2*>(ipFunctor); 
     if(lpFunctor1x2) 
     { 
     lpFunctor1x2->execute(NULL, NULL); 
     } 
    } 
} 

Я не уверен, что может быть достигнуто при таком подходе, который не мог более легко быть достигнуто с шаблоном Visitor, как отметил Дрю.

Смежные вопросы