Post

CPP Reflection in Action

CPP Reflection in Action

反射的定义

Reflection: Introspection (内省) + Intercession (调解)

  • Introspection: Ability of a program to examine itself
  • Intercession: Ability of a program to modify itself

  • Runtime feature of modern programming languages: Java, C#, Go, …

  • Use cases: Code generation
    • Serialization
    • O/R-Mapping
    • CLI Argument Parsing

反射 (Reflection) 是程序在运行时动态访问、检测和修改自身结构的能力,包括类型信息、成员变量、方法等元数据的操作。其核心功能可分为:

  1. 内省 (Introspection):运行时获取类型名称、成员列表、继承关系等元信息
  2. 动态操作:通过类型名创建对象、调用方法、修改属性值
  3. 元编程支持:结合代码生成技术实现编译时反射(如 C++ 提案 P2996

C++ 的挑战在于缺乏原生反射支持,需通过 RTTI、宏、模板或第三方库实现。例如 Java 的 Class 对象可直接获取元信息,而 C++ 的 typeid 仅能提供有限类型名称。

Evaluating Reflection Support in C++23

  • Introspection (runtime):
    • Run-time type information (RTTI)
  • Introspection (compile-time):
    • Type Traits
    • Template metaprogramming
    • Concepts and constraints
  • Intercession (compile-time):
    • Template metaprogramming
    • Compile-time function execution
    • Preprocessor metaprogramming

Preview: C++26 Compile-Time Reflection (P2996, P1306)

示例代码 (TODO: 有编译错误 )

#include <print> #include <string> #include <experimental/meta> template<typename T> requires std::is_class_v<T> void print(const T& self) { namespace meta = std::meta; template for(constexpr meta::info i : meta::define_static_array(meta::nonstatic_data_members_of(^^T))) { std::println("{} = {}", meta::identifier_of(i), self.[:i:]); } } struct test { int x; double y; std::string z; }; int main() { test t{1, 3,14, "hello"}; print(t); }

C++ 反射的实现方式

基于 RTTI 的有限反射

运行期的类型,C++ 里挺有争议(跟异常类似)的功能 RTTI。(还是要强调一句,你应该考虑是否用虚函数可以达到你需要的功能。很多项目,如 Google 的,会禁用 RTTI。)

可以用 typeid 直接来获取对象的实际类型,例如:

#include <iostream> #include <typeinfo> #include <boost/core/demangle.hpp> using namespace std; using boost::core::demangle; class shape { public: virtual ~shape() {} }; class circle : public shape { }; int main() { shape* ptr = new circle(); auto& type = typeid(*ptr); cout << type.name() << endl; cout << demangle(type.name()) << endl; cout << boolalpha; cout << (type == typeid(shape) ? "is shape\n" : ""); cout << (type == typeid(circle) ? "is circle\n" : ""); delete ptr; }

在 GCC 下的输出:

circle is circle

Refer

This post is licensed under CC BY 4.0 by the author.
Share