我希望能够自省一个c++类的名称,内容(即成员及其类型)等。这里我说的是原生c++,而不是托管c++,托管c++有反射。我意识到c++使用RTTI提供了一些有限的信息。哪些附加库(或其他技术)可以提供这些信息?
当前回答
Ponder是一个c++反射库,用于回答这个问题。我考虑了这些选择,决定自己做一个,因为我找不到一个符合我所有要求的。
虽然这个问题有很好的答案,但我不想使用大量宏,也不想依赖Boost。Boost是一个很棒的库,但也有很多小型定制的c++ 0x项目,它们更简单,编译时间更快。能够从外部装饰一个类也有好处,比如包装一个不支持c++ 11的c++库。它是CAMP的分支,使用c++ 11,不再需要Boost。
其他回答
I did something like what you're after once, and while it's possible to get some level of reflection and access to higher-level features, the maintenance headache might not be worth it. My system was used to keep the UI classes completely separated from the business logic through delegation akin to Objective-C's concept of message passing and forwarding. The way to do it is to create some base class that is capable of mapping symbols (I used a string pool but you could do it with enums if you prefer speed and compile-time error handling over total flexibility) to function pointers (actually not pure function pointers, but something similar to what Boost has with Boost.Function--which I didn't have access to at the time). You can do the same thing for your member variables as long as you have some common base class capable of representing any value. The entire system was an unabashed ripoff of Key-Value Coding and Delegation, with a few side effects that were perhaps worth the sheer amount of time necessary to get every class that used the system to match all of its methods and members up with legal calls: 1) Any class could call any method on any other class without having to include headers or write fake base classes so the interface could be predefined for the compiler; and 2) The getters and setters of the member variables were easy to make thread-safe because changing or accessing their values was always done through 2 methods in the base class of all objects.
It also led to the possibility of doing some really weird things that otherwise aren't easy in C++. For example I could create an Array object that contained arbitrary items of any type, including itself, and create new arrays dynamically by passing a message to all array items and collecting the return values (similar to map in Lisp). Another was the implementation of key-value observing, whereby I was able to set up the UI to respond immediately to changes in the members of backend classes instead of constantly polling the data or unnecessarily redrawing the display.
也许您更感兴趣的是,您还可以转储为类定义的所有方法和成员,而且是字符串形式。
该系统的缺点可能会让您望而却步:添加所有消息和键值非常繁琐;它比没有反射要慢;你会讨厌看到boost::static_pointer_cast和boost::dynamic_pointer_cast遍布你的代码库;强类型系统的局限性仍然存在,您实际上只是将它们隐藏了一些,所以它不那么明显。字符串中的错别字也不是一个有趣或容易发现的惊喜。
As to how to implement something like this: just use shared and weak pointers to some common base (mine was very imaginatively called "Object") and derive for all the types you want to use. I'd recommend installing Boost.Function instead of doing it the way I did, which was with some custom crap and a ton of ugly macros to wrap the function pointer calls. Since everything is mapped, inspecting objects is just a matter of iterating through all of the keys. Since my classes were essentially as close to a direct ripoff of Cocoa as possible using only C++, if you want something like that then I'd suggest using the Cocoa documentation as a blueprint.
你可以通过Boost::Hana库中的BOOST_HANA_DEFINE_STRUCT实现很酷的静态反射功能。 Hana非常通用,不仅适用于您所想到的用例,还适用于许多模板元编程。
c++的开箱即用不支持反射。这很可悲,因为它让防御性测试变得很痛苦。
有几种进行反思的方法:
使用调试信息(不可移植)。 在代码中加入宏/模板或其他源代码方法(看起来很难看) 修改编译器(如clang/gcc)以生成数据库。 使用Qt moc方法 提高反映 精确平坦的反射
第一个链接看起来最有希望(使用mod的clang),第二个讨论了一些技术,第三个是使用gcc的不同方法:
http://www.donw.org/rfl/ https://bitbucket.org/dwilliamson/clreflect https://root.cern.ch/how/how-use-reflex
现在有一个c++反射工作组。查看c++ 14 @ CERN的新闻:
https://root.cern.ch/blog/status-reflection-c
编辑13/08/17:
自最初的帖子以来,已经有了一些关于反思的潜在进展。下面提供了关于各种技术和状态的更多细节和讨论:
简要介绍静态反射 静态的反射 静态反射设计
然而,在不久的将来,在c++中实现标准化的反射方法看起来并不有希望,除非社区对支持c++中的反射有更多的兴趣。
下面是基于上次c++标准会议反馈的当前状态:
对反思建议的反思
编辑13/12/2017
Reflection看起来正在向c++ 20或更高版本的TSR迈进。然而运动是缓慢的。
镜子 镜像标准方案 镜纸 包括反射在内的元编程
编辑15/09/2018
TS草案已送交国家机构进行投票。
文本可以在这里找到:https://github.com/cplusplus/reflection-ts
编辑11/07/2019
反射TS已完成功能,并将于2019年夏天接受评论和投票。
元模板编程方法将被更简单的编译时代码方法所取代(在TS中没有反映出来)。
TS草案截至2019-06-17
编辑10/02/2020
这里有一个在Visual Studio中支持反射TS的请求:
https://developercommunity.visualstudio.com/idea/826632/implement-the-c-reflection-ts.html
作者David Sankel谈论TS:
http://cppnow.org/history/2019/talks/ https://www.youtube.com/watch?v=VMuML6vLSus&feature=youtu.be
2020年3月17日
反思正在取得进展。“2020-02布拉格ISO c++委员会旅行报告”的报告可以在这里找到:
https://www.reddit.com/r/cpp/comments/f47x4o/202002_prague_iso_c_committee_trip_report_c20_is/
关于c++ 23正在考虑的细节可以在这里找到(包括关于反射的简短部分):
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p0592r4.html
2020年6月4日
Jeff Preshing发布了一个名为“胶合板”的新框架,它包含了一种运行时反射机制。详情请点击这里:
https://preshing.com/20200526/a-new-cross-platform-open-source-cpp-framework/
到目前为止,这些工具和方法看起来是最完善和最容易使用的。
2020年7月12日编辑
叮当实验反射叉:https://github.com/lock3/meta/wiki
有趣的反射库,使用clang工具库提取信息进行简单的反射,不需要添加宏:https://github.com/chakaz/reflang
2021年2月24日编辑
一些额外的clang工具方法:
https://github.com/Celtoys/clReflect https://github.com/mlomb/MetaCPP
2021年8月25日编辑
youtube https://www.youtube.com/watch?v=60ECEc-URP8上的ACCU在线演讲也很值得一听,它讨论了当前对标准的建议和基于clang的实现。
See:
https://github.com/lock3/meta,分支论文/p2320 编译器资源管理器:https://cppx.godbolt.org/编译器版本使用p2320中继。
这个问题现在有点老了(不知道为什么我今天一直在问老问题),但我在想BOOST_FUSION_ADAPT_STRUCT,它引入了编译时反射。
当然,这取决于你将其映射到运行时反射,这不会太容易,但在这个方向上是可能的,而不是在相反的方向上:)
我真的认为一个宏来封装BOOST_FUSION_ADAPT_STRUCT可以生成必要的方法来获得运行时行为。
我建议使用Qt。
有一个开源许可证和一个商业许可证。