当C++14已经具有泛型lambda时,在C++20中引入的模板lambda需要什么

What is the need of template lambda introduced in C++20 when C++14 already has generic lambda?

本文关键字:lambda 什么 C++20 C++14 泛型      更新时间:2023-10-16

c++14引入了通用lambda,使编写以下内容成为可能:

auto func = [](auto a, auto b){
return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");

很明显,这个通用lambdafunc的工作原理与模板函数func的工作原理一样。

为什么C++委员会决定为通用lamda添加模板语法?

C++14泛型lambda是生成具有operator ()的函子的一种非常酷的方法,如下所示:

template <class T, class U>
auto operator()(T t, U u) const;

但不是这样的:

template <class T>
auto operator()(T t1, T t2) const; // Same type please

也不是这样:

template <class T, std::size_t N>
auto operator()(std::array<T, N> const &) const; // Only `std::array` please

也不是这样(尽管实际使用起来有点棘手):

template <class T>
auto operator()() const; // No deduction

C++14 lambda很好,但C++20允许我们轻松地实现这些情况。

由于您可以在C++20中使用模板lambdas,因此您可以用比SFINAE表达式更简单的方式限制类型:

auto lambda = []<typename T>(std::vector<T> t){};

此lambda仅适用于向量类型。

新的"熟悉的模板语法";对于C++20中引入的lambda使for_typesfor_range等构建体变得可行与C++17替代方案相比可读。

(来源:使用C++20 lambdas的编译时迭代)

在C++14和C++17通用lambda上可以完成的另一件有趣的事情是通过显式传递模板参数来直接调用operator()C++14

auto l = [](auto){ };
l.template operator()<int>(0);

C++20(另请参阅cpprreference上对<tparams>的解释):

auto l = []<typename T>(){ };
l.template operator()<int>();

上面的C++14示例非常无用:如果不给参数一个名称并使用decltype,就无法在lambda的主体中引用提供给operator()的类型。此外,我们被迫通过一个论点,即使我们可能不需要它

C++20示例显示了T在lambda的主体中是如何容易访问的,并且现在可以任意模板化null lambda。这对于上述编译时构造的实现将非常有用。

C++20接受的建议有一个很长的动机部分,并附有示例。其前提是:

当前定义的语法有几个关键原因作者认为通用lambdas是不够的。要点是使用普通函数模板可以轻松完成的一些事情要求用普通羊羔肉进行显著的环跳,或者根本做不到。作者认为lambdas很有价值足以让C++像支持正常函数一样支持它们模板。

下面是一些例子。