std :: result_of和decltype之间的区别

时间:2010-04-22 09:45:53

标签: c++ c++11 decltype result-of

我在理解C ++ 0x中对std::result_of的需求时遇到了一些麻烦。如果我理解正确,result_of用于获取调用具有某些类型参数的函数对象的结果类型。例如:

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

我能用这两种解决方案看到的唯一问题是我们需要:

  • 有一个仿函数实例,可以在传递给decltype的表达式中使用它。
  • 知道函数的已定义构造函数。

我是否正确地认为decltyperesult_of之间的唯一区别是第一个需要表达而第二个不需要?

2 个答案:

答案 0 :(得分:82)

result_ofintroduced in Boost,然后是included in TR1,最后是C ++ 0x。因此result_of具有向后兼容的优势(使用合适的库)。

decltype在C ++ 0x中是一个全新的东西,不仅限于返回函数的类型,而且是一种语言特性。


无论如何,在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;
    };

答案 1 :(得分:10)

如果你需要某种类似于函数调用的东西,#include <stdio.h> /* function returning the Square of a number */ int Square(int value) { return value * value; } /* function returning the Cube of a number */ int Cube(int value) { return value * value * value; } /* function returning the quotient of a number */ double Shrink(int value) { return (double)value / 2; } int main() { /* variable definition: */ int intValue, menuSelect, results; double shrink; intValue = 1; // While a positive number while (intValue > 0) { printf("Enter a positive Integer\n: "); scanf("%d", &intValue); { printf("Enter 1 to calculate Square, 2 to Calculate Cube, or 3 to divide input by 2, to end program enter a negative integer.\n: "); scanf("%d", &menuSelect); if (menuSelect == 1) { // Call the Square Function results = Square(intValue); printf("Square of %d is %d\n", intValue, results); } else if (menuSelect == 2) { // Call the Cube function results = Cube(intValue); printf("Cube of %d is %d\n", intValue, results); } else if (menuSelect == 3) { // Call the Divisor function shrink = Shrink(intValue); printf("The quotient of %d is %g\n", intValue, shrink); } else { printf("Invalid menu item, only 1, 2 or 3 is accepted\n"); } } } return 0; } 就不适用了。 std::result_of可以为您提供任何表达式的类型。

如果我们仅限于确定函数调用的返回类型的不同方法(在decltype()std::result_of_t<F(Args...)>之间),则存在差异。

decltype(std::declval<F>()(std::declval<Args>()...)定义为:

  

如果表达   std::result_of<F(Args...)很好   当被视为一个时形成的   未评估的操作数(第5条),   成员typedef类型应命名为   输入INVOKE (declval<Fn>(), declval<ArgTypes>()...)   否则,不得有会员   类型。

decltype(INVOKE (declval<Fn>(), declval<ArgTypes>()...));result_of<F(Args..)>::type之间的区别就在于decltype(std::declval<F>()(std::declval<Args>()...)。除了INVOKE可以直接调用(函数对象类型或函数或函数指针)之外,直接使用declval / decltype除了输入的时间要长一些之外。 F还支持指向成员函数的指针和指向成员数据的指针。

最初,使用result_of / declval保证了SFINAE友好的表达式,而decltype可能会给您一个硬错误而不是扣减失败。这已在C ++ 14中得到纠正:std::result_of现在必须是SFINAE友好的(感谢this paper)。

因此,在符合标准的C ++ 14编译器上,std::result_of非常优越。它更清晰,更短,并且正确支持更多std::result_of_t<F(Args...)> s

<小时/> 除非您在不希望允许指向成员的指针的上下文中使用它,否则F会在您可能希望它成功的情况下成功失败。

有例外。虽然它支持指向成员的指针,但如果您尝试实例化无效的 type-id std::result_of_t将无效。这些将包括返回函数或按值抽取类型的函数。例:

result_of

正确的用法是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&()>的详细信息。