C++14 引入了通用 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的模板语法?
C++14 引入了通用 lambda,使得编写以下代码成为可能:
auto func = [](auto a, auto b){
return a + b;
};
auto Foo = func(2, 5);
auto Bar = func("hello", "world");
func
的工作方式就像一个模板化函数func
一样清晰明了。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允许我们无需麻烦地实现这些情况。
(auto a, decltype(a) b)
解决第一个问题(相同类型)。 - Sebastian Machb
不会被推导出来,而是其参数将会隐式转换为 a
的类型。 - Quentin自从C++20可以使用模板化lambda表达式,你可以比SFINAE表达式更容易地限制你的类型:
auto lambda = []<typename T>(std::vector<T> t){};
这个lambda仅适用于向量类型。
consteval
与新语法有什么关系?虽然它听起来很酷,但我不理解其相关性。 - StoryTeller - Unslander Monicafor_types
和for_range
这样的结构比C++17的替代方案更加可行和易读。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。这对于实现上述编译时构造非常有用。
被C++20接受的提案(链接)有一个详细的动机部分,并附有示例。其中的前提是:
目前用于定义通用lambda表达式的语法被作者认为存在几个关键原因不足。简而言之,一些通过普通函数模板轻松完成的事情要使用通用lambda表达式需要跳过重重障碍才能完成,或者根本无法完成。作者认为lambda表达式很有价值,C++ 应该像普通函数模板一样支持它们。
之后有相当多的示例。