std :: result_of和decltype之间的区别
我在理解C ++ 0x中std::result_of
的需求时遇到了一些麻烦。 如果我理解正确, result_of
用于获取调用具有某些types参数的函数对象的结果types。 例如:
template <typename F, typename Arg> typename std::result_of<F(Arg)>::type invoke(F f, Arg a) { return f(a); }
我真的没有看到与以下代码的区别:
template <typename F, typename Arg> auto invoke(F f, Arg a) -> decltype(f(a)) //uses the f parameter { return f(a); }
要么
template <typename F, typename Arg> auto invoke(F f, Arg a) -> decltype(F()(a)); //"constructs" an F { return f(a); }
我可以看到这两个解决scheme唯一的问题是我们需要:
- 有一个函子的实例在传递给decltype的expression式中使用它。
- 知道函数的定义构造函数。
我认为decltype
和result_of
唯一的区别是第一个需要一个expression,而第二个不需要?
result_of
在Boost中引入 ,然后包含在TR1中 ,最后在C ++ 0x中。 因此, result_of
具有向后兼容的优点(具有合适的库)。
decltype
在C ++ 0x中是一个全新的东西,并不仅限于函数的返回types,而且是一种语言特性。
无论如何,在gcc 4.5上, result_of
是通过decltype
:
template<typename _Signature> class result_of; template<typename _Functor, typename... _ArgTypes> struct result_of<_Functor(_ArgTypes...)> { typedef decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) ) type; };
如果你需要的东西类似于函数调用, std::result_of
就不适用。 decltype()
可以给你任何expression式的types。
如果我们仅限于确定函数调用返回types的不同方式( std::result_of_t<F(Args...)>
和decltype(std::declval<F>()(std::declval<Args>()...)
),那么是有区别的。
std::result_of<F(Args...)
被定义为:
如果expression式
INVOKE (declval<Fn>(), declval<ArgTypes>()...)
在作为INVOKE (declval<Fn>(), declval<ArgTypes>()...)
操作数(条款5)处理时形成良好,则成员types定义types应将types命名为decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));
否则,不应有成员types。
result_of<F(Args..)>::type
和decltype(std::declval<F>()(std::declval<Args>()...)
INVOKE
就是关于这个INVOKE
。使用declval
/ decltype
除了types要长得多之外,只有在F
是可直接调用的时候才是有效的(函数对象types或函数或函数指针), result_of
还支持指向成员函数的指针和指向成员数据的指针。
最初,使用declval
/ decltype
保证一个SFINAE友好的expression,而std::result_of
可能会给你一个硬错误,而不是扣除失败。 这已经在C ++ 14中得到纠正: std::result_of
现在需要SFINAE友好(感谢这篇论文 )。
因此,在符合C ++ 14的编译器中, std::result_of_t<F(Args...)>
是严格优越的。 它更清晰,更短,正确地支持更多的F
s ‡ 。
†除非您在不希望允许指向成员的上下文中使用它,否则std::result_of_t
会在您希望失败的情况下成功。
‡有例外。 虽然它支持指向成员的指针,但如果尝试实例化无效的types标识 ,则result_of
将不起作用。 这些将包括一个函数返回一个函数或按值抽象types。 例:
template <class F, class R = result_of_t<F()>> R call(F& f) { return f(); } int answer() { return 42; } call(answer); // nope
正确的用法应该是result_of_t<F&()>
,但这是一个细节,你不必记住decltype
。