网站首页 > 博客文章 正文
在 C++14 中新增泛型lambda时,是使用基于 auto 的语法,比较简单但也带来一定的局限性,因此在 C++20 中进行改进,新增模板语法的泛型 lambda 。让我们先回顾一下基于 auto 语法的泛型 lambda ,以及其局限性,然后再看 C++20 新增的基于模板的泛型 lambda 。
(C++14)基于 auto 的泛型 lambda
C++14 中的泛型 lambda ,是使用 lambda 参数中的 auto 关键字来表示不同的类型,一个例子如下:
#include <iostream>
#include <string>
using std::cout, std::endl, std::string;
int main( int argc, char * argv[] )
{
auto f1 = [] ( auto x, auto y ) { return x + y; };
cout << &f1 << endl;
string (*fp1)( string, string ) = f1;
double (*fp2)( double, int ) = f1;
cout << (void *)fp1 << " " << (void *)fp2 << endl;
double a1 = f1( 2, 5.0 );
string a2 = fp1( "2", "5.0" );
cout << a1 << " " << a2 << endl;
return 0;
}
上述代码编译和执行的结果为:
[smlc@test code]$ g++ -std=c++20 a12.cpp
[smlc@test code]$ ./a.out
0x7ffcef96de2f
0x401f18 0x401f4b
7 25.0
由于 lambda 表达式实际定义的是一个闭包类(ClosureType),通过重载 operator () 来提供仿函数的调用。通过 auto 关键字定义的泛型 lambda ,相当于如下的定义:
struct {
template <typename T, typename U>
auto operator() ( T x, U y ) const { return x + y; }
};
基于 auto 的泛型 lambda 的局限性
基于 auto 的泛型 lambda ,最主要的局限性,是 auto 描述是整个类型,而不能像模板一样细化类型的模式。例如如果想 lambda 的参数类型是某种类型的数组(std::vector<T>),当前基于 auto 的泛型 lambda 无法表示,只能将参数定义成所有类型,然后再通过其他手段限制只能是数组类型(std::vector<T>),同时,如果想获取数组里面的具体类型,也需要使用其他手段来获取。
template <typename T> struct is_std_vector : std::false_type { };
template <typename T> struct is_std_vector<std::vector<T>> : std::true_type { };
auto f = [ ] ( auto vecType ) {
static_assert( is_std_vector< decltype( vecType ) >::value, "" ); // <1> 额外的判断std::vector<T>
using T = typename decltype( vecType )::value_type; // <2> 使用其他手段获取数组的具体类型
// ... other code ...
};
其他还有很多类似的需要细化类型的情况,例如多个参数之间的类型有关联,或者是要去掉类型 const 等附加信息,这些都需要通过 decltype 来获取类型然后再进行各种处理,反而使代码更复杂了,因此增加模板语法的 lambda 是有必要的。
(C++20)新增基于模板的 lambda 语法
C++20中新增了基于模板的lambda语法,对于上面的情况可以更简洁的描述,和其他模板的语法也保持一致:
auto f = [ ] < typename T > ( std::vector<T> vecType ) { // <1> 无需额外判断std::vector<T>,具体数组类型也可以直接使用T
// ... other code ...
}
语法上比较简单,不需要额外的 template 关键字,直接在 “ [ ] ” 和 “ ( ... ) ” 之间增加 “ < ... > ” 表示模板参数,然后在 lambda 参数和函数体中,就可以使用模板参数中描述的类型了。
基于模板的lambda也可以同时使用auto类型的参数,但不建议这样使用,混合使用这两种方式并不能带来额外的好处,反而使代码更加难懂。既然已经使用了模板,那么auto类型的参数也改为模板参数类型好了。
【往期回顾】
猜你喜欢
- 2025-08-03 C++语法进阶-字符:字符变量(char)
- 2025-08-03 c++26新功能—Read-Copy-Update
- 2025-08-03 为什么Linux之父那么讨厌C++ 他骂的这几点。句句扎心
- 2025-08-03 为什么Linux之父那么讨厌C++ 他骂的这几点!句句扎心
- 2025-08-03 20道qiao牛逼的c++/c面试题
- 2025-08-03 C++学习教程_C++语言随到随学_不耽误上班_0基础
- 2025-08-03 20天轻松入门《C++第四章——函数》——4经坛教育
- 2025-08-03 看完侯捷老师所有C++视频之后的总结
- 2025-08-03 C++11+ 泛型编程(模板)
- 2025-08-03 C++20并发库新成员jthread(续)
你 发表评论:
欢迎- 08-03 Docker 命令入门实战:搞懂这些才算真正入门!
- 08-03Docker 常用命令分类汇总
- 08-03docker常用命令大全,看这一篇就够了
- 08-03Docker命令大全详解(39个常用命令)
- 08-03Docker 常用命令手册
- 08-03Docker命令最全详解(39个最常用命令)
- 08-03Docker命令最全详解(29个最常用命令)
- 08-03C++语法进阶-字符:字符变量(char)
- 最近发表
- 标签列表
-
- ifneq (61)
- 字符串长度在线 (61)
- googlecloud (64)
- flutterrun (59)
- powershellfor (73)
- messagesource (71)
- plsql64位 (73)
- vueproxytable (64)
- npminstallsave (63)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- nacos启动失败 (64)
- ssh-add (70)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- qcombobox样式表 (68)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)