Get return value type in C ++

Suppose we have a function f that returns a value of some unknown type (let's call it T ) and takes a value of type T as an argument (and possibly has some other arguments). How to get return type f in C ++ 14?

There is a way to do this if we know what types of arguments (via std::result_of ). Is it possible if we know all types of arguments except T ?

Example:

 template <class F> // F is functor with T operator()(T a, T b) class A { // Here I want to do // T some_function(T some_arg) { ... } } 
+8
source share
2 answers
 template <typename T> struct return_type; template <typename R, typename... Args> struct return_type<R(Args...)> { using type = R; }; template <typename R, typename... Args> struct return_type<R(*)(Args...)> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...)> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) &> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) &&> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) const> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) const&> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) const&&> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) volatile> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) volatile&> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) volatile&&> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) const volatile> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) const volatile&> { using type = R; }; template <typename R, typename C, typename... Args> struct return_type<R(C::*)(Args...) const volatile&&> { using type = R; }; template <typename T> using return_type_t = typename return_type<T>::type; 

Test:

 #include <type_traits> struct Functor { int operator()(int i, int j) { return i + j; } }; template <class F> struct A { using T = return_type_t<decltype(&F::operator())>; T some_function(T some_arg) { return some_arg; } }; int main() { A<Functor> a; static_assert(std::is_same<decltype(a.some_function(1)), int>::value, "!"); } 

Demo

+10
source

Based on the excellent answer of @Piotr S., for arbitrary types of functors, if you know that there is only one operator() overload with the correct "pattern", so to speak, then you can do something like this:

 // leave undefined template<class C, class T> T return_type_helper(T (C::*)(T)); template<class C, class T> T return_type_helper(T (C::*)(T) const); // 10 additional combinations of ref- and cv- qualifiers omitted, because I'm lazy template<typename T> using functor_return_type = decltype(return_type_helper(&T::operator())); 

This activates overload resolution and the output of the template argument to determine the correct operator() .

And then you can combine these two:

 template <typename... T> struct voider { using type = void; }; template <typename... T> using void_t = typename voider<T...>::type; template<typename T, typename = void> struct combined_return_type; template<typename T> struct combined_return_type<T, void_t<typename return_type<T>::type>> { using type = typename return_type<T>::type; }; template<typename T> struct combined_return_type<T, void_t<functor_return_type<T>>> { using type = functor_return_type<T>; }; template <typename T> using return_type_t = typename combined_return_type<T>::type; 

Demo

+5
source

Source: https://habr.com/ru/post/976272/


All Articles