关于c ++ 11中的std :: result_of

时间:2014-07-21 14:12:47

标签: c++ c++11

据我所知,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;
}

这两种形式有什么区别?

2 个答案:

答案 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