我注意到反射是其他语言的开发人员在c ++中非常缺乏的一个特性。对于某些应用,我真的能明白为什么!如果您有反射,那么编写像IDE的自动完成这样的东西要容易得多。如果我们拥有它,那么序列化API肯定会变得更容易。
另一方面,c ++的一个主要原则是不支付你不使用的东西。这完全有道理。这是我喜欢的c ++。
但我发现可能会有妥协。为什么编译器没有为std::type_info
结构添加扩展?没有运行时开销。二进制文件可能会变得更大,但这可能是一个简单的编译器开关来启用/禁用,说实话,如果你真的担心空间节省,你可能会禁用异常和RTTI。
有些人引用模板问题,但编译器已经为模板类型生成了std::type_info
结构。
我可以想象像-fenable-typeinfo-reflection
这样的g ++开关可能会变得非常流行(像boost / Qt / etc这样的主流库很容易检查生成使用它的代码,如果有的话,在这种情况下最终用户没有比翻转开关更有成本的好处。我不认为这是不合理的,因为像这样的大型可移植库已经依赖于编译器扩展。
那么为什么这不常见呢?我想我错过了什么,这有什么技术问题?
编辑:只有几个指标重新成为膨胀的论点:
我查看了一个相当大的Qt项目(约45,000 LoC)并测量了metaObjects的大小。我觉得这是一个合理的指标,因为Qt moc系统是一个相当详尽的反射系统(类型,函数,枚举,成员和一些Qt特定概念,如“属性”)。总共 67个元对象,所以不是一个微不足道的数量,但没有什么疯狂,加起来5479字节。但是,几乎所有这些都是32字节或更少(最大的是1427字节)。考虑到即使是最简单的程序,现代编译器也会生成4K以上的二进制文件,这些数字并不算太多。虽然我很乐意看到这样的内容应用于STL
,看看它是如何展开的。
答案 0 :(得分:1)
通常使用反射表明软件设计不佳;正确使用接口和多态就足以完成对反射所做的任何事情。如果要将额外的信息添加到std :: type_info中,它确实会导致程序膨胀。模板的问题不是你不能从它们生成std :: type_info,而是你可以获得大量的类型,因此模板的每个实例化都会产生你需要的另一个std :: type_info对象。你使用编译器开关的建议并没有真正帮助或有意义......首先,标准永远不会指定编译器开关,因为那将是特定于实现的,但假设它是这样做的...如果您想使用来自禁用了反射的库的类的反射,会发生什么?如果大多数库禁用反射 - 他们可能会这样做 - 那么它将严重限制该功能的实用程序,如果大多数库没有禁用它,那么你将不使用它而付费。
答案 1 :(得分:1)
而不是强迫我使用某种运行时反射方法,我宁愿使用编译时反射功能来生成我需要的信息。
这样我就不必为实际上没有使用的信息付费,并且可以根据需要使用元编程来生成接口代码,而无需额外的预构建步骤或一些精细的声明性EDSL。
Caspin提到了一种可能的方法here。说实话,我很惊讶这个主题似乎从来没有被推到C ++中。
答案 2 :(得分:0)
也许C / C ++中的众多类型使得灵活的反射编程变得困难。能够处理任何原始类型的假设数据库或序列化接口需要[unsigned] int,short,[long] long,char,float,[long] double,其数组,与之相关的函数等特殊情况。到名称mangler的接口。
不是我认为这是一个很好的理由。几年前我在Boost MPL中编写了一个反射SQL界面,这很麻烦。使用“原生”设施本来会更好,更容易。
我认为大多数人通过额外的预处理实现反射,例如Apple的Mach Interface Generator和GNU和Microsoft的类似工具。
对我而言,比C ++缺乏支持更令人惊讶的是,在推动竞争的新兴语言中,例如D和(无论如何)Go。