C++ lambda模板
在 C++ 中,Lambda 模板 指的是能够像普通函数模板一样,接受泛型参数或显式模板参数的 Lambda 表达式。
Lambda 模板的发展经历了两个阶段:
- C++14 的泛型 Lambda(Generic Lambdas):使用
auto关键字实现隐式模板化。 - C++20 的显式模板 Lambda(Explicit Template Lambdas):引入了 `` 语法,提供了真正完整的模板能力。
一、泛型 Lambda
在 C++14 中,如果你在 Lambda 的参数列表中使用 auto,编译器会自动将其转换为一个成员模板函数。
1 | |
虽然 auto 很方便,但是也有一些问题:
- 无法强制要求多个参数类型相同: 比如
[](auto a, auto b)允许a是int,b是double - 获取参数类型极其繁琐: 如果需要知道参数的类型来定义局部变量或进行类型别名(
using),就必须使用难看的decltype。[](auto x) { using T = decltype(x); ... } - 无法直接匹配容器模板: 如果想写一个只接受
std::vector的 Lambda,用auto很难表达
二、Lambda 模板
为了解决上述局限性,C++20 引入了显式模板参数列表,语法是在 [] 和 () 之间加上 <typename T>。
基本语法结构如下:
1 | |
下面以三个例子分别说明 Lambda 模板是如何解决上面提到的泛型 Lambda 所存在的问题。
强制多个参数类型相同
1
2
3
4
5
6auto addSame = []<typename T>(T a, T b) {
return a + b;
};
int x = addSame(1, 2); // 正确,T 被推导为 int
// double y = addSame(1, 2.0); // 编译错误!T 无法同时推导为 int 和 double获取类型并进行完美转发
1
2
3
4
5
6
7
8
9// C++14 做法:必须使用 decltype 提取类型
auto forward_c14 = [](auto&& arg) {
doSomething(std::forward<decltype(arg)>(arg));
};
// C++20 做法:直接使用模板参数 T,优雅且符合常规模板习惯
auto forward_c20 = []<typename T>(T&& arg) {
doSomething(std::forward<T>(arg));
};嵌套模板匹配
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include <vector>
#include <iostream>
int main() {
// 只有当传入的是 std::vector<T> 时才匹配,并且能直接拿到元素类型 T
auto printVector = []<typename T>(const std::vector<T>& vec) {
// 在这里 T 就是元素的实际类型(例如 int 或 std::string)
T sum{};
for (const auto& elem : vec) {
sum += elem;
}
std::cout << "Sum: " << sum << '\n';
};
std::vector<int> v{1, 2, 3};
printVector(v); // OK
// printVector(10); // 编译错误:10 不是 std::vector 类型
}
三、底层原理
Lambda 本质上是一个匿名的仿函数(Functor)结构体。
当你写下这个 C++20 Lambda 模板时:
1 | |
C++ 编译器会在后台将其展开为类似下面的结构体:
1 | |
因为 operator() 是一个成员模板函数,所以它只有在被调用时才会被实例化(Instantiated)。
C++ lambda模板
http://example.com/2026/06/09/C++-lambda模板/