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式中使用它。
  • 知道函数的定义构造函数。

我认为decltyperesult_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..)>::typedecltype(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