|
不管 C,我来单独说说 C++吧。
先讲为什么还没有。C++ 没有反射的原因,是因为还没有人提出一个反射的提案,能够在标准委员会里得到充分的认可,达成“共识”,从而进入 C++ 标准。
一个特性要进入 C++ 标准是很难的。C++ 已经有了很多的特性,被认为是一种非常复杂的语言。这种情况,加特性需要非常慎重,需要总体上有足够的提升,同时不会太多加重学习者的负担,还要满足 C++ 的零开销抽象之类的理念,门槛是相当高的。加上这两年由于疫情影响,C++ 标准委员会开会也大多通过远程,影响了沟通效率,进展速度上总体偏低。
但没有反射只是现状,不是未来。C++ 里反射,更精确地说是“静态反射”,一直是一个热烈讨论中的话题。有很多的标准提案和讨论。Bjarne 老爷子在 HOPL4 论文里也讨论了 2013 年以来的进展。中文版参见:
《在拥挤和变化的世界中茁壮成长:C++ 2006–2020》§9.6.2我强烈推荐 Andrew Sutton 在这方面的工作。他的关于静态反射的演讲也都非常棒,比如:
Reflection: Compile-Time Introspection of C++ - Andrew Sutton [ ACCU 2021 ]但可惜的是,在 C++23 的时间窗里还是没有静态反射,我们至少需要等到 C++26 了……
<hr/>那我们现在怎么办呢?——可以利用模板和宏来自己实现。
我在项目中已经自己实现和使用静态反射相当一段时间了。最典型的应用,正如别人提到的,是序列化和反序列化。其他我用到的用法还有:
- 用通用的函数模板来打印支持反射的结构体
- 用通用的函数模板来对结构体进行逐成员的比较
- 用通用的函数模板来复制异质同构的结构体(成员之间有一一对应关系,但类型可以不同)
- 在复制中逐成员进行字节序转换
- 复制两个结构体中的同名字段
- ……
项目代码不是开源的,不能直接分享。目前我知道的关于自己实现静态反射的中文资料是:
- @netcan 的《如何优雅的实现 C++ 编译期静态反射》
- 我的极客时间专栏的第 40 讲(预计 2022/06/27 下周一上线)
罗能的文章中讲述了静态反射的基本原理,而我的工作则基于他的思想进行了进一步的拓展。(如果我没记错的话,虽然极客时间是需要付费的,但任何专栏都可以免费读四讲,所以你完全可以在本周之后过去只读那一讲。)
我最后实现的效果是,对于下面的代码:
DEFINE_STRUCT(
S1,
(int)v1,
(bool)v2,
(string)msg
);
DEFINE_STRUCT(
S2,
(long)v1,
(bool)v2
);
S1 s1{1, false, &#34;test&#34;};
S2 s2;
copy_same_name_fields(s1, s2);
编译器可以产生下面这样的高效汇编代码:
movsx rax, DWORD PTR s1[rip]
mov QWORD PTR s2[rip], rax
movzx eax, BYTE PTR s1[rip+4]
mov BYTE PTR s2[rip+8], al这显然是其他支持反射的语言所无法做到的! |
|