在一般情况下这是不可取的。 (请注意,这很容易std::function<T(A)>
指定什么,例如argument_type
是:这只是A
!它在类型定义中可用。)
可以要求每个函数对象类型指定其参数类型,并反过来要求从 lambda 表达式生成的闭包类型这样做。事实上,C++0x 之前的功能(例如自适应函子)仅适用于此类类型。
然而,我们正在通过 C++0x 来改变这一点,并且有充分的理由。其中最简单的就是重载:带有模板化的函子类型operator()
(又名多态函子)简单地接受所有类型的参数;那么应该怎样做argument_type
是?另一个原因是通用代码(通常)尝试对其操作的类型和对象指定最少的约束,以便更容易(重新)使用。
换句话说,通用代码不是really有兴趣给出Functor f
, typename Functor::argument
be int
. It's 多得多有趣的是f(0)
是一个可以接受的表达方式。为此,C++0x 提供了诸如decltype
and std::declval
(方便地将两个包装在里面std::result_of
).
在我看来,您有两种选择: 要求传递给模板的所有函子都使用 C++03 风格的约定来指定argument_type
等等;使用下面的技术;或重新设计。我推荐最后一个选项,但这是你的决定,因为我不知道你的代码库是什么样的,也不知道你的要求是什么。
对于单态函子类型(即无重载),可以检查operator()
成员。这适用于 lambda 表达式的闭包类型。
所以我们声明这些助手
template<typename F, typename Ret, typename A, typename... Rest>
A
helper(Ret (F::*)(A, Rest...));
template<typename F, typename Ret, typename A, typename... Rest>
A
helper(Ret (F::*)(A, Rest...) const);
// volatile or lvalue/rvalue *this not required for lambdas (phew)
接受一个指向至少带有一个参数的成员函数的指针。现在:
template<typename F>
struct first_argument {
typedef decltype( helper(&F::operator()) ) type;
};
[ 一个精心设计的特征可以连续查询左值-右值/常量/易失性重载,并公开第一个参数(如果它对于所有重载都相同),或者使用std::common_type
.]