How can I detect the return type and parameter types of nullary and unary function pointers, std::function objects, and functors (including lambdas)?
Boost’s function_traits and functional traits don’t quite get me there out of the box, but I’m open to supplementing or replacing them.
I could do something like this:
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 );
};
But how should I specialize for functors/lambdas?
Update: Perhaps something like in this answer to a different question, but translated from overloading to specialization?
It’s not possible in the general case for functors, i.e. class types using
operator(). This includes lambda objects, too. Consider a case whereoperator()is overloaded:What should
result_typebe?Note that, as a workaround, some protocols (e.g.
boost::apply_visitorfrom Boost.Variant) require that aresult_typebe present in the class, with the assumption that all overloads, while accepting different types, all return a type compatible with thisresult_type.And of course given some types
T0 ... Tn,std::result_of<functor(T0, ..., Tn)>::typegives the return type associated to the parameter types.In the case where exactly one overload of
operator()is present[1], you can take theoperator()member and inspect that.functor_traits<not_overloaded>::typehas typedouble (not_overloaded::*)(double) consthere, and with just a bit of effort you can extract from this what you want. (e.g. a specialization of the formRet (T::*)(Args...) constwill match that type.)[1]: but a functor can provide functionality by implicitly converting to a function pointer/reference, too, so you could miss that