1. 静态反射a. 编译期与离线期的对比b. 离线期的实践2. 动态反射与动态类型运行时3. 编译期反射a. 现有设施下的实践b. 未来的新标准

注脚

展开查看详情

1.C++反射的应用与实践 卜恪 PureCPP

2. 什么是反射? 2018中国C++大会-purecpp.org  程序对自身程序结构认知的能力 • 能够使用数据结构来描述数据类型和其成员 • 能够主动地遍历这些成员

3. 反射可以做什么? 2018中国C++大会-purecpp.org  序列化与反序列化  GUI库中对数据显示的自动化  对象关系映射(ORM)  与其他语言互操作  提供更强大的运行期特性

4. C++反射现状 2018中国C++大会-purecpp.org  没有原生的语言反射基础设施  只有一个在TS状态的反射提案  还有cppers造轮子的血泪史 2018中国C++大会-purecpp.org

5. Struggle On Reflection 2018中国C++大会-purecpp.org  静态反射 • 编译期反射 - 编译期的数据结构 • 离线期反射 - 代码生成  动态反射 - 运行期的数据结构  野路子 2018中国C++大会-purecpp.org

6. 反射元信息 2018中国C++大会-purecpp.org  类型的元信息 • 成员字段的元信息 • 参数元信息 • 字段的参数元信息 • 参数名 • 成员方法的元信息 • 参数的类型元信息 • 方法名 • 构造函数的元信息 • 方法的形参参数元信息 • 形参参数元信息 • 方法返回参数的元信息 • More … • 基类的元信息

7.项目中反射的应用 2018中国C++大会-purecpp.org C++ Core 引擎接口 GamePlay接口 引擎特性边界 业务边界 静态反射预处理 Runtime Bridge C++动态类型运行时 CLI运行时 Lua MemoryScope Virtual Machine Scheduler VM CORE Editor RunScope 策划边界 Execute Model Behavior Tree Node Graph State Machine Scripting 2018中国C++大会-purecpp.org

8.1. 静态反射 a. 编译期与离线期的对比 b. 离线期的实践 目 录 2. 动态反射与动态类型运行时 3. 编译期反射 a. 现有设施下的实践 b. 未来的新标准 2018中国C++大会-purecpp.org

9. 静态反射 - 编译期 2018中国C++大会-purecpp.org  标记方式 • 侵入式 • 能够处理私有成员 • 侵入导致对类型的修改 • 处于class-scope • 非侵入式 • 只能处理公有成员 • 无需修改需要标记的用户类型 • 处于namespace-scope

10. 静态反射 - 编译期 2018中国C++大会-purecpp.org  数据访问 • 等价tuple • 类型 • 与反射类型大小及对其属性相同 • 指向成员的指针(pointer to member data)的列表 • 编译期常量 • 无需考虑大小及对其属性

11. 编译期反射 - 遍历 2018中国C++大会-purecpp.org  显式地遍历访问 • static-for using std::index_sequence  visitor模式 • 类似visitor访问boost.variant

12. 静态反射 - 离线期 2018中国C++大会-purecpp.org  在编译前解析程序的AST • 通常仅解析接口头文件  遍历AST生成结构化数据 • AST的结构不利于数据的访问 • 提取类型和模板的引用关系  Code Generation

13. 2018中国C++大会-purecpp.org 编译期反射 离线期反射  语法和语义都完整  许多语法和语义丢失  受限于C++编译器的特性  独立之外的预处理程序,能够实  需要实现额外的编译期代码的中间 现复杂的需求 层  需要生成额外的代码

14. 静态反射 - 选型 2018中国C++大会-purecpp.org  静态反射承担引擎接口到业务逻辑层的导出工作  编译期反射由于语言设施还不够完善,有需求无法满足  编译期将引入大量的标记代码  编译期将引入大量而不可控的模板元代码  选择以离线期反射作为静态反射的方案

15.项目的离线期工具clangen 2018中国C++大会-purecpp.org 代码生成 生成cli外观 提供给编辑器 libclang 生成JSON读写 序列化与反序列化 引擎接口 头文件 AST 结构化数据 生成Lua binding的代码 提供给Lua脚本 生成动态类型运行时 增强C++的动态特性

16. 项目的离线期工具clangen 2018中国C++大会-purecpp.org  Libclang解析接口头文件 • 将Libclang导入到C# • ClangSharp自更新  遍历Libclang AST生成结构化数据  模板引擎DotLiquid作代码生成

17. Libclang的使用 2018中国C++大会-purecpp.org  设置系统头文件路径  妥善处理C++的类型  Libclang的一些使用限制

18. 设置头文件路径 2018中国C++大会-purecpp.org  确定VCTool Chain的版本 • Microsoft.VisualStudio.Setup.Configuration寻找VisualStudio的安装目录和配置 • $(YourVisualStudioPath)/VC/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt  查询注册表确定Windows Kits的安装目录  确定libclang include命令行参数 • 计算$(VC_IncludePath)与$(WindowsSDK_IncludePath)绝对路径 • 绝对路径作为-I参数

19. 处理C++的类型 2018中国C++大会-purecpp.org  内建类型和抽象数据类型(ADT)  类型修饰符带来的衍生类型 • const和volatile修饰符 • 指针类型 • 左值与右值引用 • 数组,尤其是大小未明确的数组类型(int a[]) • 指向成员的函数及指向成员的数据类型  Type define & type alias • namespace-scope & class-scope • 从基类继承而来的 • 依赖模板参数的类型

20. 使用限制 2018中国C++大会-purecpp.org  Libclang可以且仅能看到源码的AST • 合成的函数和操作符对AST不可见 • 类模板实例化后的实体类型的结构对AST不可见  模板的类型参数坍塌 • typedef和type alias会丢失 • std::string到basic_string<char, char_traits<char>, allocator<char>>  无法准确地索引到实例化类型的模板特化 • 全特化是普通类,可以正确处理 • 偏特化只能索引到主模板

21.使用限制 2018中国C++大会-purecpp.org

22. 项目的离线期工具clangen 2018中国C++大会-purecpp.org  对模板的支持 • <type_traits> on Clang AST • 处理的是实例化的类型,而不是处理模板 • 处理了标准库的容器及迭代器 • 统一处理字符串

23. 一点小建议 2018中国C++大会-purecpp.org  原则上避免在模块级别的接口中使用模板 • 为libclang的使用招致诸多麻烦 • ABI问题和ODR问题  可以避免接口头文件包含系统头文件

24.编译期的C++ 2018中国C++大会-purecpp.org

25.运行期的C++ 2018中国C++大会-purecpp.org 爱裸奔 类型擦除

26. 运行期设施简陋 2018中国C++大会-purecpp.org  typeof operator 和 std::type_info  virtual table: 动态分派  dynamic_cast: 动态类型转换

27. 动态反射 - 需要完善的设施 2018中国C++大会-purecpp.org  运行时获取类型的元信息  通过类型的元信息操作实体对象 • 成员变量的访问和设置 • 成员函数的调用 • 运行期的类型检查与类型转换  与静态代码解耦,消除 • 显式的表达式 • 显式的字面量 • 显式的函数调用 SCRIPTING!  C++动态类型运行时

28.动态反射 - PONDER 2018中国C++大会-purecpp.org

29. 动态反射 - PONDER 2018中国C++大会-purecpp.org  注册类型的元信息到runtime type system中  通过元信息创建默认实例  对字段的Get和Set  通过成员方法的元信息调用方法