我希望能够自省一个c++类的名称,内容(即成员及其类型)等。这里我说的是原生c++,而不是托管c++,托管c++有反射。我意识到c++使用RTTI提供了一些有限的信息。哪些附加库(或其他技术)可以提供这些信息?
当前回答
看起来c++仍然没有这个特性。 c++ 11也有延迟反射(
搜索一些宏或者自己制作。Qt还可以帮助进行反射(如果可以使用的话)。
其他回答
查看Classdesc http://classdesc.sf.net。它以类“描述符”的形式提供了反射,可以与任何标准c++编译器一起工作(是的,它可以与Visual Studio和GCC一起工作),并且不需要源代码注释(尽管存在一些处理棘手情况的pragmas)。它已经开发了十多年,并在一些工业规模的项目中使用。
你可以在这里找到另一个库:http://www.garret.ru/cppreflection/docs/reflect.html 它支持两种方式:从调试信息中获取类型信息和让程序员提供该信息。
我也对反思我的项目感兴趣,发现了这个库,我还没有尝试过,但尝试了这个家伙的其他工具,我喜欢他们的工作方式:-)
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中继。
如果你像这样声明一个指向函数的指针:
int (*func)(int a, int b);
您可以像这样在内存中为该函数分配一个位置(需要libdl和dlopen)
#include <dlfcn.h>
int main(void)
{
void *handle;
char *func_name = "bla_bla_bla";
handle = dlopen("foo.so", RTLD_LAZY);
*(void **)(&func) = dlsym(handle, func_name);
return func(1,2);
}
要使用间接方式加载局部符号,可以对调用二进制文件(argv[0])使用dlopen。
这样做的唯一要求(除了dlopen()、libdl和dlfcn.h)是知道函数的参数和类型。
周围有两种反射。
Inspection by iterating over members of a type, enumerating its methods and so on. This is not possible with C++. Inspection by checking whether a class-type (class, struct, union) has a method or nested type, is derived from another particular type. This kind of thing is possible with C++ using template-tricks. Use boost::type_traits for many things (like checking whether a type is integral). For checking for the existence of a member function, use Templated check for the existence of a class member function? . For checking whether a certain nested type exists, use plain SFINAE .
如果你想要实现1),比如查看一个类有多少个方法,或者获取一个类id的字符串表示形式,那么恐怕标准c++没有办法做到这一点。你必须使用其中任何一个
一个元编译器,如Qt元对象编译器,它翻译你的代码,添加额外的元信息。 由宏组成的框架,允许您添加所需的元信息。你需要告诉框架所有的方法、类名、基类和它需要的一切。
c++的设计考虑到了速度。如果您想要高级别的检查,就像c#或Java所做的那样,不做一些额外的工作就无法做到这一点。
推荐文章
- Windows和Linux上的c++编译:ifdef开关
- c++中size_t和int的区别是什么?
- 在C和c++中静态变量存储在哪里?
- 为什么标准迭代器范围是[begin, end]而不是[begin, end]?
- c++双地址操作符?(& &)
- 函数标题中的箭头操作符(->)
- 如何在c++中初始化一个向量
- 返回类型为'?:'(三元条件运算符)
- 当分配vector时,它们使用的是堆上的内存还是堆栈上的内存?
- 互斥实例/教程?
- 如何添加一个'或'条件在#ifdef
- 纯虚函数的实现
- 为什么在c++中声明enum时使用typedef ?
- 对静态类成员的未定义引用
- c++中“using”关键字背后的逻辑是什么?