In this answer I create a type trait:
template<typename T>
using to_string_t = decltype(to_string(declval<T>()));
This works just fine but I originally set out to use result_of
and now it's irking me that I can't figure out how to do it.
I'm trying to replace the line above with something like this:
template<typename T>
using to_string_t = result_of<to_string(T)>;
But I get a compiler error along the lines of:
error C2275: 'T': illegal use of this type as an expression
note: see declaration of 'T'
error C2974: 'std::result_of': invalid template argument for '_Fty', type expected
I've tried several other inputs to result_of
without success, can anyone help me understand what arguments result_of
is expecting here?
Let's patch it up. std::result_of
expects only types, its result should be retrieve from its type
inner typedef, and you need typename
to access said typedef because it depends on a template parameter.
template<typename T>
using to_string_t = typename std::result_of<decltype(std::to_string)(T)>::type;
^^^^^^^^ ^^^^^^^^ ^^^^^^
Or in C++14, you can drop ::type
and typename
:
template<typename T>
using to_string_t = std::result_of_t<decltype(std::to_string)(T)>;
^^
Fine ?
main.cpp:5:68: error: decltype cannot resolve address of overloaded function
Right, std::to_string
is overloaded, so we need to disambiguate it by casting it to one of its overloads.
template<typename T>
using to_string_t = typename std::result_of<decltype(static_cast<
Hold on. We need its return type to express the destination type of the cast. We're back to our starting point.
std::result_of
can't deal with overloaded functions, because the function has no definite type until the overload is resolved. decltype
is the only solution here, because it does apply overload resolution.
If you're wondering how std::result_of
can be useful, given the above limitation : it's used for overloaded functors, i.e. classes that overload the ()
operator several times. As the type of the class is known, and does not depend on the call arguments, std::result_of
works.
... But shouldn't std::to_string
always return a std::string
??