【问题标题】:Finding out the return type of a function, lambda or function找出函数、lambda 或函数的返回类型
【发布时间】:2015-01-07 15:04:16
【问题描述】:

对于this question 中的 lambdas 的情况,这似乎已解决。但那是 2011 年的答案,我正在寻找一个一般情况:lambdas、常规函数和仿函数。并且,如果可能的话,通过最现代的 c++ 语言添加。 (注:g++ -std=c++1y test.cpp)。

所以,给定一个函数(或 lambda),我试图找出它的返回类型是什么。例如,声明一个变量(简化情况)。

using namespace std;

template<typename F>
void test (F h) {
  // any of the following should be equivalent to int a; int b; int c;
  decltype(h) a; // <<<<< wrong
  result_of(h) b; // <<<<<< wrong
  result_of<decltype(h)> c; // <<<<<< wrong
}

int a_function (int i)  { 
  return 2*i; 
}

int main ()  {
  test (a_function);
}

谢谢。

【问题讨论】:

  • 当你有两个重载的h函数:int h (int)float h(float),你期望result_of(h)返回什么?
  • @Zadirion 好点。但在我的问题中,要么只有一个 h(),要么实际上 h() 将是另一个函数的输入参数。
  • 为什么要在不知道如何调用它的情况下找到函数的返回值?这有什么用?或者你知道怎么称呼它吗?

标签: c++ c++11


【解决方案1】:

假设:

  1. 您只需要返回类型。
  2. 您不知道参数类型是什么/将是什么(因此decltype()std::result_of&lt;&gt; 都不是一个选项。
  3. 作为参数传递的仿函数对象不会有重载或泛型operator()

然后您可以使用以下特征来推断任何函子对象的返回类型:

template <typename F>
struct return_type_impl;

template <typename R, typename... Args>
struct return_type_impl<R(Args...)> { using type = R; };

template <typename R, typename... Args>
struct return_type_impl<R(Args..., ...)> { using type = R; };

template <typename R, typename... Args>
struct return_type_impl<R(*)(Args...)> { using type = R; };

template <typename R, typename... Args>
struct return_type_impl<R(*)(Args..., ...)> { using type = R; };

template <typename R, typename... Args>
struct return_type_impl<R(&)(Args...)> { using type = R; };

template <typename R, typename... Args>
struct return_type_impl<R(&)(Args..., ...)> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...)> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...)> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) &> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) &> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) &&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) &&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const&&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const&&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) volatile> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) volatile> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) volatile&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) volatile&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) volatile&&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) volatile&&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const volatile> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const volatile> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const volatile&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const volatile&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args...) const volatile&&> { using type = R; };

template <typename R, typename C, typename... Args>
struct return_type_impl<R(C::*)(Args..., ...) const volatile&&> { using type = R; };

template <typename T, typename = void>
struct return_type
    : return_type_impl<T> {};

template <typename T>
struct return_type<T, decltype(void(&T::operator()))>
    : return_type_impl<decltype(&T::operator())> {};

template <typename T>
using return_type_t = typename return_type<T>::type;

测试:

#include <type_traits>

template <typename F>
void test(F h)
{
    static_assert(std::is_same<return_type_t<F>, int>{}, "!");

    return_type_t<F> i = 1;
}

int function(int i) { return 2*i; }

int c_varargs_function(...) { return 1; }

struct A
{
    int mem_function(double, float) { return 1; } 
};

int main()
{
    // Function
    test(function);

    // C-style variadic function
    test(c_varargs_function);

    // Non-generic lambda
    test([](int i) { return 2*i; });

    // Member function
    test(&A::mem_function);
}

DEMO

【讨论】:

  • 有没有办法避免你的特征(或者使用一些std 功能来压缩它)?
  • @Walter。应该有。由于特征不再是样板代码,它应该以decltype(a) 的存在方式简单地存在return_type&lt;F&gt;
  • @Walter 因为它的功能有限(正如我在开头列出的那样),我怀疑这样的特性会被引入标准库(目前没有等效的,你需要知道参数的类型您将使用,并利用decltype(func(1,2,3))std::result_of_t&lt;F(int,int,int)&gt;。还有there is no easy way 无需宏定义的帮助即可压缩它
  • @Walter 除了功能有限之外,它的用例也非常狭窄。我犹豫说“没用”,但它非常接近无用。在 C++ 中应该会出现重载:在询问类型将返回什么之前,您应该知道如何使用它。
  • 我仍然觉得令人惊讶的是,有多少人喜欢这样关于 C++ 的答案,以及有多少人喜欢使这些暴行成为可能的语言特性。
【解决方案2】:

std::result_of&lt;h(int)&gt;::type a;

(取自here。)

【讨论】:

    猜你喜欢
    • 2018-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-31
    • 1970-01-01
    • 2018-04-09
    相关资源
    最近更新 更多