【问题标题】:Calling lambda with non-parameter template argument使用非参数模板参数调用 lambda
【发布时间】:2021-11-17 19:44:42
【问题描述】:

MSVC 2019 允许我像这样定义一个 lambda,其中参数列表中不使用模板参数:

auto foo = []<bool B>() {
  return B;
};

但是,当尝试这样调用它时会出现语法错误?

foo<false>();

使用非参数模板参数调用 lambda 的正确方法是什么?

【问题讨论】:

  • foo.operator()&lt;false&gt;();

标签: c++ templates lambda c++20


【解决方案1】:

模板参数与lambdaoperator()一起使用。

(C++20 起)如果 lambda 定义使用显式模板形参列表,则该模板形参列表与 operator() 一起使用。

您可以为operator()指定非类型模板参数,以非正常样式调用lambda:

foo.operator()<false>();

【讨论】:

    【解决方案2】:

    foo 是一个函数对象。它有一个operator()。 lambda 上的模板在该运算符上,而不是在对象名称本身上。

    foo&lt;T&gt; 尝试为名称 foo 提供模板参数 T;这在这里无效。 foo&lt;T&gt;() 将模板参数提供给 foo,然后在结果上调用 ()。同样,不是这里发生的事情。

    模板变量可以按照您希望的方式工作:

    template<bool B>
    auto foo = []() {
      return B;
    };
    

    此类变量仅在全局范围内有效,但在此处 foo&lt;true&gt;() 将有效。

    因为 lambda 实际上是编译器生成的类:

    struct some_secret_name {
      template<bool B>
      auto operator()() const {
        return B;
      }
    };
    some_secret_name foo;
    

    那么“正确”的称呼方式就是丑陋的语法:

    foo.operator()<true>();
    

    老实说,这很糟糕。

    你可以像这样得到稍微好一点的语法:

    template<class T> struct tag_t {using type=T;};
    template<class T> constexpr tag_t<T> tag_v={};
    template<auto v> using value_t = std::integral_constant<std::decay_t<decltype(v)>, v>;
    template<auto v> constexpr value_t<v> value_v={};
    

    那么我们就可以了

    auto foo = []<bool B>(value_t<B>) {
      return []{
        return B;
      };
    };
    

    现在的语法是:

    foo(value_v<false>)();
    

    如果过于神奇,它看起来不那么笨拙。

    foo 现在是一个生成 lambda 的 lambda,外部 lambda 将您的模板参数作为函数参数,而内部 lambda 是主体。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-01
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多