C++20引入模板lambda的需求是什么?考虑到C++14已经有了通用lambda。

111

引入了通用 lambda,使得编写以下代码成为可能:

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

这个通用的lambda表达式func的工作方式就像一个模板化函数func一样清晰明了。
为什么C++委员会决定添加泛型lambda的模板语法?

7
如果需要使用与参数或返回类型不同的模板类型,该怎么办?如果需要在函数体内部使用,又该怎么办? - Some programmer dude
我被告知这个是一个有趣的用例。 - Max Langhof
请参考以下链接,了解不同 Lambda 版本的比较:https://www.modernescpp.com/index.php/more-powerful-lambdas-with-c-20 - schoetbi
4个回答

134

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允许我们无需麻烦地实现这些情况。


4
简洁明了。补充一下:C++14中可以通过(auto a, decltype(a) b)解决第一个问题(相同类型)。 - Sebastian Mach
16
几乎正确。使用这种解决方案,b 不会被推导出来,而是其参数将会隐式转换为 a 的类型。 - Quentin

43

自从C++20可以使用模板化lambda表达式,你可以比SFINAE表达式更容易地限制你的类型:

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

这个lambda仅适用于向量类型。


8
consteval 与新语法有什么关系?虽然它听起来很酷,但我不理解其相关性。 - StoryTeller - Unslander Monica
这更多是关于C++20在lambda表达式中添加了什么信息,而不是对问题的回答。 - Antoine Morrier

30
在C++20中引入的“熟悉的模板语法”为lambda表达式引入了新的构造方式,使得像for_typesfor_range这样的结构比C++17的替代方案更加可行和易读。
(来源:使用C ++20 lambda进行编译时迭代
对于C++14和C++17通用lambda,另一个有趣的事情是可以通过显式传递模板参数直接调用operator()C++14:
auto l = [](auto){ };
l.template operator()<int>(0);

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

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

上面的C++14示例相当无用:在lambda体中没有办法引用提供给operator()的类型,除非给参数命名并使用decltype。此外,即使我们可能不需要它,我们也被迫传递一个参数。

C++20示例展示了如何在lambda体中轻松访问T,并且现在可以任意模板化一个零元lambda。这对于实现上述编译时构造非常有用。


27

被C++20接受的提案(链接)有一个详细的动机部分,并附有示例。其中的前提是:

目前用于定义通用lambda表达式的语法被作者认为存在几个关键原因不足。简而言之,一些通过普通函数模板轻松完成的事情要使用通用lambda表达式需要跳过重重障碍才能完成,或者根本无法完成。作者认为lambda表达式很有价值,C++ 应该像普通函数模板一样支持它们。

之后有相当多的示例。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接