Detection of a functional object (functor) and lambda signs

How can I determine return type and parameter types for null and unary function pointers, std :: function objects and functors (including lambdas)?

Boost function_traits and functional features don't quite get me 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 in / lambdas functors?

Update: Perhaps something like this answer to another question , but translates from overload to specialization?

+7
source share
2 answers

This is impossible in the general case for functors, i.e. class types using operator() . This also includes lambda objects. Consider the case when operator() overloaded:

 struct functor { double operator()(double) const; int operator()(int) const; }; typedef function_traits<functor>::result_type result_type; 

What should be result_type ?

Note that as a workaround, some protocols (for example, boost::apply_visitor from Boost.Variant) require that the result_type be present in the class, provided that all overloads, when accepting different types, return a type compatible with this result_type .

And, of course, with some types T0 ... Tn , std::result_of<functor(T0, ..., Tn)>::type sets the return type associated with the parameter types.


In the case where one operator() [1] overload is present, you can take the operator() member and check this.

 struct not_overloaded { double operator()(double) const; }; template<typename T> struct functor_traits { typedef decltype(&T::operator()) type; }; 

functor_traits<not_overloaded>::type is of type double (not_overloaded::*)(double) const here, and with a little effort you can extract what you want from it. (for example, specialization of the form Ret (T::*)(Args...) const will correspond to this type.)

[1]: but a functor can provide functionality by implicitly converting to a function pointer / link so you can skip this.

+6
source

All Articles