Search code examples
c++metaprogrammingreturn-typedecltyperesult-of

Can I get the Return Type of a Function From a Signature?


So I have a ton of functions similar to these:

template <typename T>
bool Zero(const T, const T, const T);
template <typename T>
T One(const T, const T, const T, bool);
template <typename T>
T Three(const T, const T, const T, const T, const T, const T);

For each of these functions I have a wrapper which uses the return type of these functions so it looks something like this:

template <typename T>
decltype(Zero<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()))) ZeroWrapper(const T);
template <typename T>
decltype(One<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), bool())) OneWrapper(const T);
template <typename T>
decltype(Three<decltype(declval<T>().x)>(decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()), decltype(declval<decltype(declval<T>().x)>()))) ThreeWrapper(const T);

As you can see all those decltype(declval<T>().x)'s get disgustingly hard to read. Can I template a using or is there some standard function which will allow me to extract the return type from a function pointer without passing the argument types to decltype or result_of? So something like this:

template <typename T>
foo_t<Zero<decltype(declval<T>().x)>> ZeroWrapper(const T);
template <typename T>
foo_t<One<decltype(declval<T>().x)>> OneWrapper(const T);
template <typename T>
foo_t<Three<decltype(declval<T>().x)>> ThreeWrapper(const T);

Solution

  • In the function object has been endowed with a Deduction Guide which allows it to determine it's type from the argument passed to the constructor. So for example, given the function int foo() in we had to do:

    function<int()> bar(foo);
    

    In bar's function<int()> type will be derived if we simply:

    function bar(foo);
    

    Thus we can use the Deduction Guide to populate a temporary function with only the signature; thereby using function's result_type to find the result of your helper funcitons:

    template <typename T>
    typename decltype(function(Zero<decltype(declval<T>().x)>))::return_type ZeroWrapper(const T);
    template <typename T>
    typename decltype(function(One<decltype(declval<T>().x)>))::return_type OneWrapper(const T);
    template <typename T>
    typename decltype(function(Three<decltype(declval<T>().x)>))::return_type ThreeWrapper(const T);
    

    Live Example