Circle是图灵完备的编译期元编程引擎,直接扩展C++语法为编译期执行语言,无需constexpr修饰,默认启用-fconstexpr-everything,但需用circle命令而非g++/clang++调用。

Circle 编译器不支持标准 C++ 元编程,它自己就是元编程引擎
Circle 不是“用 C++ 写元编程”,而是把 C++ 语法直接扩展成编译期图灵完备的执行语言。你写的 constexpr 函数、模板特化、SFINAE 这些在 GCC/Clang 里受限的东西,在 Circle 里可以直接当普通代码跑——因为 Circle 的编译器前端本身就是解释执行的。
常见错误现象:error: constexpr function cannot call non-constexpr function 这类报错在 Circle 里几乎不会出现;反过来,如果你照着 Clang 写了一堆保守的 constexpr if + std::is_constant_evaluated() 分支,Circle 会默默忽略后半段——它默认所有代码都可编译期求值。
- 使用场景:生成类型列表、展开递归模板、读取 JSON/YAML 配置并直接构造编译期数据结构、甚至解析 AST 片段
- Circle 不区分“编译期”和“运行期”语义层,
if、for、std::vector(需启用-fexperimental-vector)都能在编译期用 - 参数差异:Circle 默认开启
-fconstexpr-everything,不需要手动加constexpr修饰符;但若要导出为标准 C++20 兼容头文件,得显式补上
如何启用 Circle 并让元编程代码真正执行
Circle 不是插件或库,它是个独立编译器,必须用 circle 命令替代 g++ 或 clang++。不换命令行工具,写再多 __meta_apply 也没用。
常见错误现象:用 g++ -x c++ -std=c++20 编译含 __reflect 的代码,报 error: use of undeclared identifier '__reflect' ——这不是语法错,是你根本没走 Circle 编译流程。
立即学习“C++免费学习笔记(深入)”;
- 安装后直接运行
circle -o main.o main.cpp,不是g++调用 Circle - 想调试元编程执行过程?加
-###看 Circle 实际展开的 AST,或用-E查看预处理+元展开后的结果 - Circle 默认禁用部分 STL 头(如
<algorithm>中非constexpr版本),需加-fno-builtin或手动实现替代逻辑
__reflect 和 __meta_apply 是核心,但别滥用反射遍历
__reflect 能拿到类成员名、类型、偏移,__meta_apply 能对每个成员调用 lambda——听起来很爽,但实际容易卡在编译时间爆炸上。Circle 的反射不是零成本抽象。
使用场景:自动生成序列化函数、验证字段命名规范、构建编译期 registry 表;不适合做深度嵌套结构的全量反射(比如整个 protobuf message 树)。
- 性能影响:一次
__reflect(Type)触发完整符号解析,如果 Type 含大量模板实例化,编译耗时可能从秒级跳到分钟级 - 兼容性注意:
__reflect返回的是 Circle 内部元对象,不能传给标准std::tuple构造函数;要用__meta_apply显式转成类型列表 - 容易踩的坑:对未定义的类(只有声明)调用
__reflect会静默失败,不是报错,而是返回空元组——务必确保类已完全定义
编译期执行的输出必须落地为常量或类型,否则白干
Circle 允许你在编译期算圆周率、解方程、甚至跑小游戏逻辑,但这些结果如果没绑定到 constexpr 变量、模板参数或 using 别名上,就只是编译器内部的中间状态,链接时消失。
常见错误现象:写了大段 int x = compute_at_compile_time();,结果运行时还是调用函数——因为没加 constexpr,Circle 没把它当编译期常量看待;或者用了 auto 推导但右侧表达式依赖运行期输入(如 argc),导致推导失败。
- 正确做法:所有要导出的结果,必须显式声明为
constexpr auto val = ...或template<auto V> struct X {}; - 类型级输出更稳定:比起推导
constexpr int,用using T = decltype(__meta_apply(...));更少受求值时机干扰 - Circle 的
__builtin_constant_p在某些上下文返回 false,别依赖它做条件分支;直接用if consteval(C++23)或 Circle 自带的if constexpr (__is_constant_evaluated())
最麻烦的点其实是心理预期:你以为写的是 C++,其实是在用一门新语言写编译器插件。变量作用域、求值顺序、错误定位方式,全都得按 Circle 的规则来,而不是靠经验猜。











