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_type
be?Note that, as a workaround, some protocols (e.g.
boost::apply_visitor
from Boost.Variant) require that aresult_type
be 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)>::type
gives 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>::type
has typedouble (not_overloaded::*)(double) const
here, and with just a bit of effort you can extract from this what you want. (e.g. a specialization of the formRet (T::*)(Args...) const
will match that type.)[1]: but a functor can provide functionality by implicitly converting to a function pointer/reference, too, so you could miss that
What's wrong with
std::result_of
?http://en.wikipedia.org/wiki/C%2B%2B0x#Uniform_method_for_computing_the_return_type_of_function_objects