Это невозможно в общем случае для функторов, то есть типов классов, использующих operator()
.Это касается и лямбда-объектов.Рассмотрим случай, когда operator()
перегружен:
struct functor {
double
operator()(double) const;
int
operator()(int) const;
};
typedef function_traits<functor>::result_type result_type;
Каким должен быть result_type
?
Обратите внимание, что в качестве обходного пути некоторые протоколы (например, boost::apply_visitor
из Boost.Variant)) требуют, чтобы result_type
присутствовал в классе, предполагая, что все перегрузки, хотя и допускают различные типы, все возвращают тип, совместимый с этим result_type
.
И, конечно, учитывая некоторые типы T0 ... Tn
, std::result_of<functor(T0, ..., Tn)>::type
дает тип возвращаемого значения, связанный с типами параметров.
В случае, когда присутствует ровно одна перегрузка operator()
[1], вы можете взять член operator()
ипроверьте, что.
struct not_overloaded {
double
operator()(double) const;
};
template<typename T>
struct functor_traits {
typedef decltype(&T::operator()) type;
};
functor_traits<not_overloaded>::type
имеет здесь тип double (not_overloaded::*)(double) const
, и, приложив немного усилий, вы сможете извлечь из этого то, что вы хотите.(например, специализация вида Ret (T::*)(Args...) const
будет соответствовать этому типу.)
[1]: но функтор может предоставлять функциональность, неявно преобразуя также указатель / ссылку на функцию, так что вы можете пропустить это