c++11variadic-templatesoverloadingdecltyperesult-of

no type named "type" in "std::result_of" ; get return type from overloading functions


I am learning how to get type of the return value of overloaded function test() vs test(double).

I modified code from a SO answer (by chris).

#include <type_traits>
#include <utility>

int test();
double test(double x);

template<typename... Ts>
using TestType = decltype(test(std::declval<Ts>()...))(Ts...);

int main() {
    std::result_of< TestType<double> >::type n = 0;
     //^ ### compile error ###
    using doubleDat = std::result_of< TestType<double> >::type ;
    doubleDat n=0;
}

I got a compile error.

error: no type named 'type' in 'std::result_of'

As I understand:-

Question: Why it doesn't compile? How to solve it?

I have read these :-

Clue: After a long search, I get faint smell that my code suffers "Most vexing parse".


Solution

  • Look at what your TestType<double> expands to:

    test(std::declval<double>())(double)
    

    test(std::decvlal<double>) is double so you get double(double)

    result_of<double(double)>::type asks if you can invoke a double with an argument of type double.

    The answer is no, because double is not callable, so there's no nested type.

    You need to read the documentation for result_of to understand how to use it. The type result_of<F(Arg)>::type is the result of invoking an F with an argument Arg. If F is callable with an argument Arg you get the return type, if it is not callable with an argument Arg then the nested type doesn't exist.

    So this would work:

    using func_type = TestType<double>;
    using doubleDat = std::result_of<func_type*(double)>::type;
    

    This creates an alias for a function of type TestType<double> (i.e. double(double)) and then asks if you can invoke a pointer to that type (i.e. double(*)(double)) with an argument of type double. And you can, so you the type is valid.