Reputation: 2313
Given a very simple, but lengthy function, such as:
int foo(int a, int b, int c, int d) {
return 1;
}
// using ReturnTypeOfFoo = ???
What is the most simple and concise way to determine the function's return type (ReturnTypeOfFoo
, in this example: int
) at compile time without repeating the function's parameter types (by name only, since it is known that the function does not have any additional overloads)?
Upvotes: 58
Views: 14656
Reputation: 968
Years later but you may be interested in my own (free) solution here (production grade, fully documented). It's a full implementation of some of the other ideas you've seen here (see responses by Barry and max66). You can target almost anything about a function however (within the limitations of C++ itself), not just the return type.
Download the code, add "TypeTraits.h" and "CompilerVersions.h" to your project, then do the following (note that you don't have to explicitly #include "CompilerVersions.h", it's automatically #included in "TypeTraits.h")
#include "TypeTraits.h"
using namespace StdExt; // Everything's in this namespace
using ReturnTypeOfFoo = ReturnType_t<decltype(foo)>;
Upvotes: -1
Reputation: 180415
You can leverage std::function
here which will give you an alias for the functions return type. This does require C++17 support, since it relies on class template argument deduction, but it will work with any callable type:
using ReturnTypeOfFoo = decltype(std::function{foo})::result_type;
We can make this a little more generic like
template<typename Callable>
using return_type_of_t =
typename decltype(std::function{std::declval<Callable>()})::result_type;
which then lets you use it like
int foo(int a, int b, int c, int d) {
return 1;
}
auto bar = [](){ return 1; };
struct baz_
{
double operator()(){ return 0; }
} baz;
using ReturnTypeOfFoo = return_type_of_t<decltype(foo)>;
using ReturnTypeOfBar = return_type_of_t<decltype(bar)>;
using ReturnTypeOfBaz = return_type_of_t<decltype(baz)>;
This technique only works if the function is not overloaded or the function do not have multiple operator()
's defined.
Upvotes: 81
Reputation: 66190
I don't know if is the simplest way (if you can use C++17 surely isn't: see NathanOliver's answer) but... what about declaring a function as follows:
template <typename R, typename ... Args>
R getRetType (R(*)(Args...));
and using decltype()
?
using ReturnTypeOfFoo = decltype( getRetType(&foo) );
Observe that getRetType()
is only declared and not defined because is called only a decltype()
, so only the returned type is relevant.
Upvotes: 19
Reputation: 302688
Most simple and concise is probably:
template <typename R, typename... Args>
R return_type_of(R(*)(Args...));
using ReturnTypeOfFoo = decltype(return_type_of(foo));
Note that this won't work for function objects or pointers to member functions. Just functions, that aren't overloaded or templates, or noexcept
.
But this can be extended to support all of those cases, if so desired, by adding more overloads of return_type_of
.
Upvotes: 29