编译期编程一直是C++的深水区。最近有人在折腾C++26反射提案时,挖出了两个新技巧:编译期键值映射表,以及一个他称为"编译期可变变量"的玩法。这篇文章聊聊具体怎么实现的。
核心灵感来自P2996R13提案里的编译期计数器示例(§3.17)。这个计数器要解决一个具体问题:编译时自动给程序元素分配唯一编号,不用手动设置、不用担心重复。实现它用了C++26反射的三个新函数:substitute、is_complete_type和define_aggregate,都在meta命名空间里。
打开网易新闻 查看精彩图片
substitute的作用是模板替换——给它一个模板反射和参数反射,返回替换后的实体反射。is_complete_type检查反射是否代表完整类型。define_aggregate则配合consteval块使用,块内代码在编译期执行一次。
打开网易新闻 查看精彩图片
计数器类TU_Ticket有两个静态consteval函数:latest返回当前值,increment把值加一。关键是利用模板特化的不完整类型状态来"存储"计数值——每次increment就定义一个新的特化版本,latest通过检查哪个特化存在来读取状态。
作者把这个思路扩展成了编译期映射表和可变变量。映射表能在编译期存取键值对,可变变量则允许在consteval块里修改状态——这在以前几乎不可能。对于写编译期状态机的开发者,这两个工具可能省掉大量模板元编程的 boilerplate。
打开网易新闻 查看精彩图片
想复现的话,需要支持P2996R13的编译器,代码已在Godbolt上跑通。反射提案还在演进,但这些技巧的原理应该比较稳定。
热门跟贴