You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import std;
voidprint_struct(auto &&value) {
constexprauto info = std::meta::remove_cvref(^^decltype(value));
constexprauto no_check = std::meta::access_context::unchecked();
staticconstexprauto members = std::define_static_array(
std::meta::nonstatic_data_members_of(info, no_check));
template for (constexprauto e : members) {
constexprauto type = type_of(e);
auto &&member = value.[:e:];
ifconstexpr (is_class_type(type)) { print_struct(member); }
else { std::println("{} {}", identifier_of(e), member); }
}
}
structPoint { double x{}; double y{}; };
intmain() { print_struct(Point{2, 3}); }
实际输出(mcpp clean --bmi-cache && mcpp run)
error: build failed
src/main.cpp:7:36: error: 'remove_cvref' is not a member of 'std::meta'; did you mean 'std::remove_cvref'?
of module std, imported at src/main.cpp:2
src/main.cpp:8:40: error: 'std::meta::access_context' has not been declared
src/main.cpp:9:40: error: 'define_static_array' is not a member of 'std'
src/main.cpp:10:18: error: 'nonstatic_data_members_of' is not a member of 'std::meta'
import std;无法暴露std::meta(P2996 反射):build.cxxflags中的-freflection未应用到 std 模块 BMI 预构建概述
当项目通过
[build].cxxflags = ["-freflection"]启用 C++26 反射时,该 flag 只传到了项目自身的源文件,没有传到预构建的std模块 BMI。结果import std;导入的是一个未带-freflection编译的 std 模块,因此std::meta、std::define_static_array、std::meta::nonstatic_data_members_of等全部缺失——尽管项目源文件本身是带-freflection编译的。这与 #99(项目与 std BMI 之间的方言不匹配)属于同一类问题。#98/#100 已经针对语言标准(
[package].standard)修复了它。但 #98 明确保留了build.cxxflags作为「附加 C++ flag」,这些 flag 不会进入 std 模块 BMI 的预构建。对大多数 flag 这没问题,但对于「决定 libstdc++ 头文件暴露哪些声明」的 flag 就会出错——-freflection正是这样一个 flag。环境
gcc@16.1.0(xlings-fromsource)mcpp.toml
src/main.cpp(最小复现)
实际输出(
mcpp clean --bmi-cache && mcpp run)注意:项目自身
main.cpp的编译命令确实带上了-freflection(通过mcpp build --verbose验证,对应步骤[.../15] g++ ... -freflection -c src/main.cpp)。唯独 std BMI 漏了这个 flag。根因
std 模块 BMI 的构建命令记录在
~/.mcpp/bmi/<fingerprint>/std-module.json:只有
std_flag(来自[package].standard的语言标准)被注入。用户的build.cxxflags(-freflection)不在 std 模块的编译命令里——尽管它确实参与了构建指纹(增删这个 flag 会改变指纹哈希,因此 mcpp 会缓存到一个不同的 std BMI 目录,但那个目录里的 BMI 仍然是不带该 flag编译出来的)。为什么这对
-freflection尤其关键:在 GCC 16 / libstdc++ 中,整个<meta>头文件都被如下条件守卫:而
__cpp_impl_reflection仅在传入-freflection时才定义(已验证:不带该 flag 时该宏未定义;带上后为202603L)。因此,一个不带-freflection编译的 std BMI 在结构上根本不可能包含std::meta。证明缺失的就是这一个 flag
手动用
-freflection重新编译缓存的 std BMI(同一条命令 +-freflection),std::meta就能通过import std;正确解析。(在混合构建中此后会冒出一个针对fmt.gcm的二次 BMI 兼容性错误,因为依赖模块的 BMI 必须针对同一个 std 重新构建——而如果这个 flag 由 mcpp 的流水线来管理,本应由它统一处理。)GCC + libstdc++ 完全支持该特性的独立验证(只要该 flag 传到了每一个接触 std 的翻译单元):
期望行为
build.cxxflags(或至少一个指定的「影响 std 的 flag」子集)应当也被拼接进 std 模块 BMI 的预构建命令,使import std;看到与项目其余部分一致的 libstdc++ 配置。由于这些 flag 已经参与了指纹计算,缓存键是正确的——只是编译命令的构造遗漏了它们。可能的修复方向(供维护者权衡)
build.cxxflags也传入std_build_commands(最简单;与已包含它们的指纹保持一致)。-freflection、-fcontracts),类比 feat: make C++ standard a first-class build setting #98 中把standard作为一等设置的做法。'std::meta' is not a member报错,从而少走弯路。相关 issue