【问题标题】:How to get return type and parameter type of a generic lambda?如何获取泛型 lambda 的返回类型和参数类型?
【发布时间】:2020-04-01 06:04:56
【问题描述】:

我想获取 lambda 的返回类型和参数类型。 Is it possible to figure out the parameter type and return type of a lambda?给出一个解决方案。但它不适用于通用 lambda。

template<typename F>
struct function_traits :public
    function_traits<decltype(&F::operator())> {};

template<typename R,typename C,typename... Args>
struct function_traits<R(C::*)(Args...)const>:public
    function_traits<R(Args...)>{
  constexpr static size_t arity = sizeof...(Args);
};

auto f1 = [](int x) {return x+1; };
Print(function_traits<decltype(f1)>::arity);  //return 1
auto f2 = [](auto x) {return x+1; };
Print(function_traits<decltype(f2)>::arity);  //error

那么如何解决获取泛型 lambda 的返回类型和参数类型呢?

【问题讨论】:

  • 请不要编辑问题以使现有答案无效。相反,请发布一个新问题。
  • 两种变体都无法编译,第一种情况导致 lambda 对象被强制转换为函数指针

标签: c++ c++11 c++14 c++17 generic-lambda


【解决方案1】:

通用 lambdas 是其中 operator() 重载是模板函数的 lambdas。如果推导出模板函数的参数,则它没有类型;只有此类模板的单独实例具有类型参数。

auto 不是类型;它是一个占位符,意思是“这是一个模板参数”。

【讨论】:

  • 现在我很困惑如何判断天气一个函数是一个模板函数......
  • 在这种情况下,您的auto lamda 没有完全定义。它仅在推断 auto 类型时定义。
  • 谢谢。所以不可能从通用 lambda 中获取参数号?
  • @haskeller 因为泛型 lambda 是带有模板 operator() 的 lambda,所以当 f2 是泛型 lambda 时,decltype(f2) 是非法表达式,因为没有使用参数。
【解决方案2】:

Lambda 无论如何都不是函数。

编译器将f1 和f2 视为具有调用运算符的类。

一些 lambda 具有到函数指针的隐式转换运算符。

Here is a link 这两个在 cppinsights 中的样子。

顺便说一句,如果您是 C++ 模板的新手,我强烈建议使用 cppinsights。 Here is a great video 谈论它,here is one 他使用 cppinsights 深入探索 lambda。

我也复制了相关代码在这里进行说明,以防链接失效。

这就是你的f1 的样子。

class __lambda_1_11
{
  public: 
  inline /*constexpr */ int operator()(int x) const
  {
    return x + 1;
  }

  using retType_1_11 = int (*)(int);
  inline /*constexpr */ operator retType_1_11 () const noexcept
  {
    return __invoke;
  };

  private: 
  static inline int __invoke(int x)
  {
    return x + 1;
  }
};

这就是你的f2 的样子。

class __lambda_2_11
{
  public: 
  template<class type_parameter_0_0>
  inline /*constexpr */ auto operator()(type_parameter_0_0 x) const
  {
    return x + 1;
  }
  private: 
  template<class type_parameter_0_0>
  static inline auto __invoke(type_parameter_0_0 x)
  {
    return x + 1;
  }
};

请注意,f1 有一个非模板调用运算符并且它有一个到函数指针 (int (*)(int)) 的隐式转换运算符。

f2 有一个模板调用运算符并且没有隐式转换运算符 - 因为调用运算符是一个成员函数模板。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 2016-09-16
    • 2016-11-13
    • 1970-01-01
    • 1970-01-01
    • 2011-05-11
    • 2016-08-15
    相关资源
    最近更新 更多