检测函数对象(函子)和lambda traits [英] Detecting function object (functor) and lambda traits

查看:145
本文介绍了检测函数对象(函子)和lambda traits的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何检测null和一元函数指针,std :: function对象和functor(包括lambdas)的返回类型和参数类型?



Boost的< a href =http://www.boost.org/doc/libs/1_46_1/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html =nofollow> function_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?



更新:可能类似于

这是不可能的函数的一般情况,即使用 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() member并检查。

  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]:但是函子可以通过隐式转换为函数指针/引用来提供函数,所以你可能错过了


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 where operator() is overloaded:

struct functor {
    double
    operator()(double) const;

    int
    operator()(int) const;
};

typedef function_traits<functor>::result_type result_type;

What should result_type be?

Note that, as a workaround, some protocols (e.g. boost::apply_visitor from Boost.Variant) require that a result_type be present in the class, with the assumption that all overloads, while accepting different types, all return a type compatible with this result_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 the operator() member and inspect that.

struct not_overloaded {
    double
    operator()(double) const;
};

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

functor_traits<not_overloaded>::type has type double (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 form Ret (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

这篇关于检测函数对象(函子)和lambda traits的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆