现代 C++ 编程实战
吴咏炜
前 Intel 资深软件架构师
34199 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
加餐 (1讲)
现代 C++ 编程实战
15
15
1.0x
00:00/00:00
登录|注册

40 | 如何在编译期遍历数据?

解决字段缺失问题
按字段名复制结构体
对象拷贝
对象字段查找
对象打印
函数模板输出 tuple 类型对象内容
tuple 提供编译期索引和类型访问
结构体字段的复制与比较
数据结构的序列化与反序列化
利用模板和宏
在编译期对结构体的字段进行操作
cppreference.com 关于待决名的文档
Microsoft /Zc:preprocessor 文档
罗能的博客文章
罗能提出的改进意见
实现数据结构的序列化
扩充数据处理能力
重要的编译期编程工具
工程化代码的差异
GitHub 上的完整实现和测试
拷贝同名字段
同时遍历两个结构体
结构体数据遍历
类型特征判断是否支持静态反射
字段名称的比较与输出
字段名称作为类型
字段访问
字段定义
结构体定义
REPEAT_ON
STRIP
PAIR
PASTE
STRING
GET_ARG_COUNT
遍历方法
tuple 与结构体的区别
应用场景
实现手法
定义
参考资料
特别致谢
课后思考
内容小结
实现细节
应用案例
静态反射的使用
编译期使用字段名称
DEFINE_STRUCT
宏基础
编译期数据遍历
静态反射
静态反射与编译期数据遍历

该思维导图由 AI 生成,仅供参考

你好,我是吴咏炜。
你考虑过 tuple 和普通的结构体存在哪些区别吗?
显然,一个字段没有名字,一个字段有名字——这是一个非常基本的区别。
其他还有吗?
有。
对于 tuple,标准 C++ 里提供了很多机制,允许你:
知道 tuple 的大小(数据成员数量)
通过一个编译期的索引值,知道某个数据成员的类型
通过一个编译期的索引值,对某个数据成员进行访问
利用这些信息,我们可以额外做很多事情,比如,像第 38 讲描述的那样,用一个函数模板来输出所有 tuple 类型对象的内容。这些功能是普通结构体所没有的!
在 C++ 的静态反射到来之前,我们想在结构体里达到类似的功能,只能自己通过一些编程技巧来实现。本讲我们就会介绍一种手工实现静态反射的方法,能够让结构体在用起来跟原来没感觉有区别的情况下,额外提供类似 tuple 的功能,甚至还更多。毕竟,结构体里的字段是有名字的,可以产生更可读的代码。我们还能进一步利用编译期的字符串模板参数技巧(第 39 讲),使用字段名称这一数据,让下面的代码能通过编译:
DEFINE_STRUCT(
S1,
(int)v1,
(bool)v2,
(string)msg
);
DEFINE_STRUCT(
S2,
(long)v1,
(bool)v2
);
S1 s1{1, false, "test"};
S2 s2;
copy_same_name_fields(s1, s2);
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了C++中的静态反射机制及其应用。通过对比`tuple`和普通结构体的区别,强调了`tuple`在C++标准中提供的机制,允许获取`tuple`的大小、通过编译期索引值获取数据成员的类型以及访问数据成员。文章提出了手工实现静态反射的方法,使得结构体能够在使用上与原来无异,同时提供类似`tuple`的功能。通过宏基础的介绍,展示了如何在给定索引值的情况下,合适地产生静态反射所需要的全部信息和方法。此外,还介绍了如何在编译期使用字段名称,并提出了识别对静态反射的支持的方法。整体而言,本文为读者提供了丰富的技术细节和实现手法,使其能够快速了解静态反射的定义和使用。文章内容涵盖了静态反射的基本原理、实现方法以及应用场景,对于C++开发者具有一定的参考价值。文章还提到了静态反射的应用场景,如拷贝同名字段、序列化、反序列化等,展示了静态反射在自动化处理数据结构方面的潜在价值。文章中的代码示例和实现细节展示了作者对静态反射的深入理解和实践经验,为读者提供了丰富的实践参考。整体而言,本文对C++中的静态反射机制进行了全面而深入的探讨,为读者提供了宝贵的技术指导和实践经验。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《现代 C++ 编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(4)

  • 最新
  • 精选
  • 当初莫相识
    这些选学的文章,难度太高,我只能草草阅过,段位不够😂

    作者回复: 这一讲属于高级技巧了,难度是高点。我主要是想分享一点可能用得上的技术。 另外,即使没看懂,你也可以试试看使用这种方式。毕竟,使用 STL 并不要求你能够写出 STL。

    2022-10-19归属地:江苏
    3
  • 李云龙
    昨天提出的问题有误,重新请教老师:为什么 cout << is_same_v<decltype("Hi"_cts), decltype("He"_cts)> ; 返回的是true,但是 cout << is_same_v<decltype(cts_wrapper<"Hi">{}), decltype(cts_wrapper<"He">{}) > 返回的是false?前者我的理解是按照字符串的字符个数进行对比,后者为什么可以按照字符的值进行了对比?下面的两段代码的模板参数都是compile_time_string cts,为什么对比的结果会不一样? template <compile_time_string cts> constexpr auto operator""_cts() { return cts; } template <compile_time_string cts> struct cts_wrapper { static constexpr compile_time_string str{ cts }; };

    作者回复: 你看它们两者的类型就知道了: https://godbolt.org/z/GfqP4dEME 后者的结果是 cts_wrapper<compile_time_string<3ul>{char [3]{(char)72, (char)105}}> 这种样子:字符串的内容也编码进去了。

    2023-11-26归属地:北京
    2
    1
  • 李云龙
    我在实际工程中遇到过c++ STL 容器需要序列化的场景,当时我们采用的方法是将容器中的数据转存到Json中,然后利用Json库的序列化和反序列化功能。我觉得这样的序列化应该是效率不高。学习了本讲后,我觉得STL容器的序列化有了一个新的方案:将容器中的数据转存至结构体中,然后使用本讲的静态反射进行序列化。

    作者回复: 静态反射时常用于序列化。 但是,“将容器中的数据转存至结构体中”有点让人皱眉。你是可以直接对容器进行序列化的…… 一个范例是 struct_pack 项目。你可以搜索了看一下。

    2023-11-24归属地:北京
    1
  • 钱虎
    2022-07-18
收起评论
显示
设置
留言
4
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部