使用CRTP实现Mixin时GCC下触发-Wextra的“成员缺失初始化器”警告问题
使用CRTP实现Mixin时GCC下触发-Wextra的“成员缺失初始化器”警告问题
这个问题我之前在GCC上踩过类似的坑,咱们先理清楚来龙去脉:
你通过CRTP模式把listed和eq两个mixin组合到my_mixin中,使用C++聚合初始化(带指定成员的语法)创建对象时,GCC触发了-Werror=missing-field-initializers警告,提示my_mixin::<anonymous>缺少初始化器,但同样的代码在Clang 16和MSVC 19上完全正常。正如你提到的,这确实是GCC的一个bug——它错误地将CRTP继承的基类识别成了需要显式初始化的匿名成员。
不用禁用警告的情况下,有几种办法可以绕过这个问题:
方法1:显式初始化CRTP基类
在聚合初始化列表中,显式地对继承的ops基类进行初始化,告诉GCC这部分已经被处理了:
int main(int, char**) { const my_mixin carrier = { ops<my_mixin, listed, eq>{}, // 显式初始化CRTP基类 .uuid = 1234, .name = std::string{"name"}, }; }
方法2:给my_mixin添加显式构造函数
放弃聚合初始化,改为使用自定义构造函数来初始化对象,这样就不会触发聚合相关的警告了:
struct my_mixin: ops<my_mixin,listed,eq> { uint32_t uuid; std::string name; // 自定义构造函数,可根据需求调整参数和初始化逻辑 my_mixin(uint32_t u, std::string n) : uuid(u), name(std::move(n)) {} }; int main(int, char**) { const my_mixin carrier{1234, "name"}; }
方法3:利用C++20的指定初始化器初始化基类
如果你的项目已经支持C++20,可以直接用指定初始化器语法显式初始化基类:
int main(int, char**) { const my_mixin carrier = { .ops<my_mixin, listed, eq> = {}, // C++20支持对基类的指定初始化 .uuid = 1234, .name = std::string{"name"}, }; }
这些方法都不需要禁用GCC的警告,同时能解决这个bug带来的编译问题。
备注:内容来源于stack exchange,提问作者CJCombrink
相关产品推荐
相关产品推荐

