如何检测nullary和unary函数指针,std :: function对象和functor(包括lambdas)的返回类型和参数类型?
Boost的function_traits和functional traits并没有让我开箱即用,但我愿意补充或更换它们.
我可以这样做:
namespace nsDetail { class Dummy { Dummy(); }; } template<class Fn> struct FnTraits; template<class R> struct FnTraits<R(*)()> { typedef nsDetail::Dummy ParamType; typedef R ReturnType; typedef R Signature(); }; template<class R,class P> struct FnTraits<R(*)(P)> { typedef P ParamType; typedef R ReturnType; typedef R Signature( P ); }; template<class R> struct FnTraits< std::function<R()> > { typedef nsDetail::Dummy ParamType; typedef R ReturnType; typedef R Signature(); }; template<class R,class P> struct FnTraits< std::function<R(P)> > { typedef P ParamType; typedef R ReturnType; typedef R Signature( P ); };
但是我应该如何专注于functor / lambdas呢?
更新:也许类似于this answer to a different question,但从重载转换为专业化?
解决方法
在一般情况下,对于仿函数,即使用operator()的类类型,这是不可能的.这也包括lambda对象.考虑一下operator()重载的情况:
struct functor { double operator()(double) const; int operator()(int) const; }; typedef function_traits<functor>::result_type result_type;
result_type应该是什么?
请注意,作为一种变通方法,一些协议(例如来自Boost.Variant的boost :: apply_visitor)要求在类中存在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形式的特化将匹配该类型.)