【问题标题】:Get the type of the return value in C++在 C++ 中获取返回值的类型
【发布时间】:2014-10-05 10:43:12
【问题描述】:

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

如果我们知道参数类型,就有办法做到这一点(通过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) { ... }
}

【问题讨论】:

  • 你有你的意思的代码示例吗?
  • @MarcoA。是的,但它有点具体
  • decltype(f(...)),其中... 填充了函数可以采用的类型的参数。因此,例如,如果 f 是 f(int, float),你会做 decltype(f(0, 0.f))
  • @TheOne 但我不知道所有的参数类型!除了我想找到的,我什么都知道
  • 如果F 同时定义int operator()(int)double operator()(double) 会怎样?你会返回什么类型的?

标签: c++ types c++14 decltype


【解决方案1】:
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

【讨论】:

  • 你能在每个模板类之间添加空行吗? atm 很难读懂
  • 当然,不适用于任意函子。而且您还应该对普通函数类型进行部分特化。
  • @T.C.: struct return_type&lt;R(*)(Args...)&gt; 是你所谓的标准函数类型的特化吗?因为它已经存在了
  • 我说的是return_type&lt;R (Args...)&gt;
  • 它代表for an ellipsis
【解决方案2】:

在@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.

【讨论】:

    猜你喜欢
    • 2012-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多