我在理解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
和result_of
之间的唯一区别是第一个需要表达而第二个不需要?
答案 0 :(得分:82)
result_of
是introduced 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&()>
的详细信息。