首页 > 解决方案 > 为什么我不能使用 labmda 作为非类型模板参数?

问题描述

我想使用 lambda 作为模板参数,但它不会在 c++17 中编译。例如temp_bar<int, lambda1>这里不起作用。似乎非类型参数是有限的。谁能解释为什么不允许这样做?启用此功能将使生活变得更加容易。

template<typename T>
bool to_bool(T o)
{
    return bool(o);
}
template <typename T, auto F=to_bool<T>>
class temp_bar
{
public:
    temp_bar(T o)
            : _data{o}
    {
        if(F(o))
            std::cout << "OK\n";
    }
private:
    T _data;
};

int main()
{
    temp_bar<int> bar1{1};
    auto lambda1 = [](int o){return o==2;};
    temp_bar<int, lambda1> bar2{2};

    return 0;
}

标签: c++lambdac++17

解决方案


忽略lambda1is not的声明,constexpr因此不是常量表达式,因此无论如何都不能用作非类型模板参数(NTTP)这一事实,不允许这样做的主要原因是 lambdas 不是C ++中的特殊事物。lambda 只是由编译器创建的用户定义类型,具有专门的构造函数、基于捕获列表的成员以及operator()符合 lambda 函数体和签名的重载。没有它们,lambda 所做的一切都是你做不到的。

在 C++ 中,lambda 只是简写符号;而已。

因此,如果用户定义的类型不能用作 NTTP,而 lambda 是用户定义的类型,那么您不能将 lambda 用作 NTTP。这就是他们被禁止的原因。

请注意,虽然 C++20 确实允许将某些用户定义的类型用作 NTTP,但目前的标准不保证任何特定的 lambda 是否可以用作 NTTP。用作 NTTP 的用户定义类型必须提供强大的结构相等性,并且标准中的任何内容都不需要任何 lambda,即使是无捕获的 lambda,也必须提供强大的结构相等性。一个实现可以这样做,但是这样的代码是不可移植的。


推荐阅读