Search code examples
c++templatestype-traitsresult-of

why std::result_of can't accept function type?


I have this code

int f(int i){
        return i;
}
int main(){
    cout << std::boolalpha;
    using f_1 = decltype(f);
    using f_2 = decltype((f));
    cout << is_same<std::result_of_t<f_1(int)>, int>::value<< endl; // ERROR
    cout << is_same<std::result_of_t<f_2(int)>, int>::value<< endl; // OK
    return 0;
}

If I am correct, decltype(f) will return the type of the function which will be int(int). decltype((f)) will return the type of reference of the function which will be int(&)(int). In the documentation of result_of, it said: F must be a callable type, reference to function, or reference to callable type. Invoking F with ArgTypes... must be a well-formed expression. So is that mean a function type is not an callable type?

Error info is

1.23.cpp: In function ‘int main()’:
1.23.cpp:35:38: error: ‘type name’ declared as function returning a function
   35 |     cout << is_same<std::result_of_t<f_1(int)>, int>::value<< endl; // ERROR
      |                                      ^~~
1.23.cpp:35:46: error: template argument 1 is invalid
   35 |     cout << is_same<std::result_of_t<f_1(int)>, int>::value<< endl; // ERROR
      |                                              ^
1.23.cpp:35:52: error: template argument 1 is invalid
   35 |     cout << is_same<std::result_of_t<f_1(int)>, int>::value<< endl; // ERROR
      |                                                    ^

Solution

  • A function cannot have a function type as return type. It can have a reference-to-function return type though.

    So already in terms of the simple meaning of the syntax f1(int), the program is ill-formed. It would denote the type of a function that takes an int and returns a function type (f1).

    The behavior of std::result_of using an invented function type as template argument is a bit weird and causes these issues. That's one of the reasons it has been replaced with std::invoke_result which takes the callable and argument types as individual template arguments, so that no function type needs to be invented.