Circle不是Rust过程宏替代品,而是编译器级元编程工具:其__meta/__reflect在语法树生成后、语义分析前的元阶段运行,直接参与编译流水线,需Circle编译器专属支持,无法跨翻译单元调用或与标准C++工具链兼容。

C++ 没有过程宏,Circle 也不是 Rust 的过程宏替代品 —— 它是编译器级元编程工具,行为和设计目标完全不同。
Circle 的 __meta 和 __reflect 不是过程宏
Circle 提供的元编程能力(如 __meta、__reflect、__eval)运行在 Circle 编译器的“元阶段”(metastage),即语法树生成后、语义分析前。它能遍历 AST、生成新声明、修改类型,但这些操作不是“在宏展开时插入代码”,而是直接参与编译流水线。
- Rust 过程宏接收 TokenStream → 输出 TokenStream,与宿主编译器解耦;Circle 元函数是 C++ 语法的扩展,必须用 Circle 编译器才能执行
- Circle 不支持“在任意 crate 中导入并调用一个元函数”,它的元逻辑必须与被处理代码在同一翻译单元或显式
#include_meta - 没有
proc_macro::TokenStream类接口,无法做基于字符串/语法节点的自由拼接,所有生成都受限于 Circle 的 AST 操作 API
想实现“类似 derive 的自动 impl”,得用 __reflect + __meta 手写遍历
比如为结构体自动生成 operator==:Circle 不会像 #[derive(PartialEq)] 那样自动触发,你得显式调用一个元函数,并传入类型名。
// 假设你定义了这个元函数
__meta void gen_eq(const char* type_name) {
auto t = __reflect(type_name);
if (!t.is_struct()) return;
__code {
bool operator==(const <code>type_name</code>& a, const <code>type_name</code>& b) {
// 手动遍历字段生成比较逻辑
<code>__foreach_member</code>(t, m, {
if (a.<code>m.name</code> != b.<code>m.name</code>) return false;
});
return true;
}
}
}
<p>// 然后在普通代码里显式调用:
gen_eq("MyStruct");- 字段遍历靠
__foreach_member,不能用标准 C++ 反射(C++20std::reflect还没落地,Circle 是私有实现) -
__code块内不能自由插值变量名,m.name必须出现在合法上下文中,否则编译失败 - 生成的函数作用域默认在当前命名空间,不会自动 inline 或
constexpr,需手动加限定符
Circle 元函数不能跨编译单元传播,也无法 hook 标准宏展开
你不能写一个 #define MY_DERIVE(T) __meta_gen_impl(T),然后期望它在别处 MY_DERIVE(Foo) 就触发元逻辑 —— Circle 的元阶段只对明确标记为元上下文的代码生效。
立即学习“C++免费学习笔记(深入)”;
-
#define展开发生在预处理阶段,早于 Circle 元阶段;__meta函数只在__meta块或__code块中调用才执行 - 头文件中写的元函数,若未被任何
__meta调用引用,会被完全忽略,不会产生副作用 - 没有类似 Rust
proc-macro-hack的绕过机制;Circle 不提供“把普通函数调用重写成元调用”的能力
真正容易被忽略的是:Circle 的元编程不是“可选特性”,而是整个编译模型的一部分。一旦用了 __reflect,你就锁死了 Circle 工具链,且所有依赖项都必须用 Circle 编译 —— 这和 Rust 过程宏可以混用 stable 编译器、仅构建时依赖 proc-macro crate 的轻量集成,根本不在同一维度上。











