8

如何检测 nullary 和 unary 函数指针、std::function 对象和仿函数(包括 lambda)的返回类型和参数类型?

Boost 的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 );
};

但是我应该如何专注于仿函数/lambdas?

更新:也许类似于this answer to a different question,但从重载转换为专业化?

4

2 回答 2

6

在函子的一般情况下是不可能的,即使用operator(). 这也包括 lambda 对象。考虑一个operator()重载的情况:

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

    int
    operator()(int) const;
};

typedef function_traits<functor>::result_type result_type;

应该result_type是什么?

请注意,作为一种解决方法,某些协议(例如boost::apply_visitor来自 Boost.Variant)要求 aresult_type存在于类中,并假设所有重载在接受不同类型时都返回与 this 兼容的类型result_type

当然给定一些类型T0 ... Tnstd::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将匹配该类型。)

[1]:但是仿函数也可以通过隐式转换为函数指针/引用来提供功能,因此您可能会错过

于 2011-06-01T13:54:51.337 回答
1

有什么问题std::result_of

http://en.wikipedia.org/wiki/C%2B%2B0x#Uniform_method_for_computing_the_return_type_of_function_objects

于 2011-06-01T13:51:03.770 回答