获取C++中返回值的类型

问题描述:

假设我们有一个函数f,它返回某个未知类型的值(我们称之为T)并将T类型的值作为参数(可能还有一些其他参数)。我如何在C++ 14中获得返回类型f获取C++中返回值的类型

如果我们知道参数类型(通过std::result_of),就有办法做到这一点。如果我们知道除T之外的所有参数类型,是否可能?

例子:

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) { ... } 
} 
+0

你有什么样的代码样本吗? – 2014-10-05 10:43:53

+0

@MarcoA。是的,但它是一种特定的 – wrwt 2014-10-05 10:44:59

+0

'decltype(f(...))',其中'...'填充了该函数可以采用的类型参数。因此,举例来说,如果f是'f(int,float)',你可以执行'decltype(f(0,0.f))' – Creris 2014-10-05 10:48:16

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; 

测试:

#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

+0

你可以在每个模板类之间添加空行吗?这是很难读取它atm – Creris 2014-10-05 11:00:56

+1

当然,不适用于任意函子。而且你也应该对普通函数类型进行部分特化。 – 2014-10-05 11:30:13

+0

@ T.C .:是'struct return_type '你称为*标准函数类型*的专门化吗?因为它已经存在 – 2014-10-05 11:33:55

大厦@Piotr S.的出色答卷,对于任意函子类型,如果你知道只有一个operator()过载正确的“模式”,可以这么说,那么你可以做这样的事情:

// 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())); 

这激活了重载和模板实参推演,以确定正确的operator()

然后你可以结合这两个:

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