据我所知,std::result_of
的可能实现是
template<class F, class... ArgTypes>
struct result_of<F(ArgTypes...)>
{
typedef decltype(
std::declval<F>()(std::declval<ArgTypes>()...)
) type;
};
但是当我使用std::result_of
时,我遇到了一些麻烦。
int f(int x)
{
return 0;
}
template<typename T>
void Test(const T& t)
{
decltype(std::declval<T>()(std::declval<int>())) i1 = 1; // ok
typename std::result_of<T(int)>::type i2 = 2; // compile error:
// function returning a function
// I think this means the same thing just as above, right?
}
int main()
{
Test(f);
return 0;
}
这两种形式有什么区别?
答案 0 :(得分:5)
std::result_of
在C ++ 11 [meta.trans.other]中声明为表57:
template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;
它需要:
Fn
应为可调用类型(20.8.1),对函数的引用或对可调用类型的引用。表达式decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...))
应该很好。
可调用类型在[func.def] / 3中定义:
可调用类型是函数对象类型(20.8)或指向成员的指针。
函数对象类型在[function.objects] / 1中定义:
函数对象类型是一个对象类型(3.9),它可以是函数调用中 postfix-expression 的类型(5.2.2,13.3.1.1) )。 ...
在您的计划中,f
是对int(int)
类型函数的引用,因此T
会推断为函数类型int(int)
。请注意,函数类型不是要传递给Fn
的类型std::result_type
的有效选项之一。对函数的引用是可接受的类型,但是:您应该将完整类型的Test
参数传递给result_of
而不是T
({{3 }}):
template<typename T>
void Test(const T&)
{
decltype(std::declval<T>()(std::declval<int>())) i1 = 1;
typename std::result_of<const T& (int)>::type i2 = 2;
}
关于两种表单之间的区别,请记住std::declval
始终返回引用类型;具体而言,std::declval<T>()
会返回T&&
。所以
decltype(std::declval<T>()(std::declval<int>()))
询问使用T&&
参数调用int&&
时返回的类型。
答案 1 :(得分:4)
[basic.compound]描述了C ++中的函数类型:
- functions ,它们具有给定类型的参数并返回
void
或给定类型的引用或对象
因此,函数类型的返回类型部分本身不能是函数类型,因此T(int)
时T = int(int)
不是C ++类型系统中的有效类型。
此外,[dcl.fct] / 8澄清:
函数不应具有类型数组或函数的返回类型
另请注意,i1
行的实际模拟值为typename std::result_of<T>::type i2
。