Объедините перегрузку функций с функторами, и в общем случае становится невозможно определить, какие аргументы можно передать вызываемой сущности.
Рассмотрим, например,
struct FunctorExample {
void operator()(int x) {...}
std::string operator()(const std::string& ) {...}
};
Если бы был какой-то способ уговорить компилятор сопоставить шаблон с аргументами, он должен был бы иметь неопределенное или ошибочное поведение при применении к FunctorExample
.
Вместо этого, как представляется, тенденция заключается в том, что когда вы хотите шаблонизировать метапрограмму с помощью функторов, вы указываете функтор и список аргументов. Примеры (от макушки головы): boost::result_of
и boost::fusion
.
Редактировать : Тем не менее, если вы хотите несколько ограничить свое внимание и можете использовать некоторый синтаксис C ++ 11 (decltype
), вы можете устроить для интроспекции немного больше:
// Support functors with a very simple operator():
template <typename T> struct argument :
public argument<decltype(&T::operator())> {};
// Pointers to member functions
template <typename C, typename R, typename A> struct argument<R(C::*)(A)>
{typedef A type;};
// Function types
template <typename R, typename A> struct argument<R(A)> {typedef A type;};
// Function pointer types.
template <typename R, typename A> struct argument<R(*)(A)> {typedef A type;};
// Now for call:
template <typename FuncType>
void call(FuncType func) {
typedef typename argument<FuncType>::type Arg;
func(Arg());
}
// example:
class FunctorInt {public: int operator()(int ) {return 0;};};
void myfunc(void *) {}
int main() {
call(myfunc);
call(FunctorInt());
}
Шаблоны Variadic могут использоваться для расширения этого материала для поддержки более чем одного аргумента.