简体   繁体   中英

about std::result_of in c++11

As I know, a possible implementation of std::result_of is

template<class F, class... ArgTypes>
struct result_of<F(ArgTypes...)>
{
    typedef decltype(
        std::declval<F>()(std::declval<ArgTypes>()...)
        ) type;
};

But when I use std::result_of I have some trouble.

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

What are the differences between these two forms?

std::result_of is declared in C++11 [meta.trans.other] Table 57 as:

template <class Fn, class... ArgTypes> struct result_of<Fn(ArgTypes...)>;

and it requires that:

Fn shall be a callable type (20.8.1), reference to function, or reference to callable type. The expression

 decltype(INVOKE(declval<Fn>(), declval<ArgTypes>()...)) 

shall be well formed.

callable type is defined in [func.def]/3:

A callable type is a function object type (20.8) or a pointer to member.

function object type is defined in [function.objects]/1:

A function object type is an object type (3.9) that can be the type of the postfix-expression in a function call (5.2.2, 13.3.1.1). ...

In your program, f is a reference to a function of type int(int) , so T is deduced to the function type int(int) . Note that a function type is not one of the valid options for the type Fn to be passed to std::result_type . A reference to function is an acceptable type, however: you should pass the full type of Test s parameter to result_of instead of only T ( Demo at Coliru ):

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

Regarding the difference between the two forms, remember that std::declval always returns a reference type; specifically std::declval<T>() returns T&& . So

decltype(std::declval<T>()(std::declval<int>()))

is asking for the what type is returned when a T&& is invoked with an int&& argument.

[basic.compound] describes what function types look like in C++:

functions , which have parameters of given types and return void or references or objects of a given type

Therefore, the return type part of a function type must not itself be a function type, and thus T(int) is not a valid type in the C++ type system when T = int(int) .

Moreover, [dcl.fct]/8 clarifies:

Functions shall not have a return type of type array or function

Note also that the actual analogue of your i1 line is typename std::result_of<T>::type i2 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM