首页 > 解决方案 > 可以将 lambdas 用作非类型模板参数吗?

问题描述

下面的代码合法吗?

template <auto Lambda>
struct A {};

int main () {
  auto lmb = [](int i){return i*i;};
  A<lmb> a;
  return 0;
}

我注意到 g++ 编译得很好,而 clang++ 返回 error: a non-type template parameter cannot have type '(lambda at main.cpp:...)'.

标签: c++templateslambdac++20non-type

解决方案


可以将 lambdas 用作非类型模板参数吗?

是的,使用已实现P0732R2 - 非类型模板参数中的类类型clang++尚未实现它的实现。

来源: https ://en.cppreference.com/w/cpp/compiler_support


请注意,lambda 至少需要constexpr(默认情况下):

当此说明符不存在时,函数调用运算符 constexpr无论如何都会存在,如果它恰好满足所有constexpr函数要求。

但是,您可以添加constexpr以获取 lambda 本身的错误,而不是在将其用作模板参数时。附带说明:您还可以将其指定consteval为使其作为非类型模板参数工作。

有状态的 lambda 可以是constexpr

constexpr auto lmb1 = [](int i) {
    static int x = 0;
    return i*i + ++x;
};

而通过引用捕获或通过复制变异 ( mutable) 捕获的 lambda 则不能。不过,通过复制 a 来捕获是可以的constexpr

通用 lambda 也可能是constexpr

constexpr auto gen_lmb = []<typename T>(T& val) {
   val += val;
   return val;
};

template <auto Lambda>
struct A {
    template<typename T>
    void doit(T&& arg) {
        std::cout << Lambda(arg) << '\n';
    }
};

//...

A<gen_lmb> ginst;

int v = 1000;
ginst.doit(v);
ginst.doit(std::string("foo "));
std::cout << v << '\n';
2000
foo foo
2000

推荐阅读