C++继承flatbuffers::NativeTable的struct花括号初始化报错原因查询
报错含义
你遇到的initializer must be brace-enclosed报错是C++编译器在聚合初始化阶段触发的,核心含义是被初始化的对象需要用花括号包裹符合要求的初始化值,这里特指TableKeyT继承来的基类flatbuffers::NativeTable子对象没有使用正确的花括号初始化语法。
报错原因
你的TableKeyT是符合C++17及以上标准要求的聚合类,满足以下条件:
- 无用户自定义的构造函数
- 所有非静态成员都是公开权限
- 无虚函数
- 公开继承自基类
NativeTable
聚合初始化的规则要求:如果聚合类存在公开基类,初始化列表的第一个元素必须对应基类子对象的初始化值,哪怕基类是空类也不能省略占位。
你原来的初始化代码TableKeyT key { std::string(sym), std::string(ex), std::string("") };直接把三个成员变量的初始化值放到列表里,编译器会把第一个std::string(sym)尝试用于初始化基类NativeTable,而空基类NativeTable只能接受空花括号{}作为初始化值,因此触发报错。
如果你的编译标准低于C++17,带基类的类不会被识别为聚合类,本身就不支持直接用成员值列表做聚合初始化,同样会触发初始化相关报错。
解决方案
方案1:补充基类初始化占位(最简便,无需修改结构体定义)
直接在初始化列表最前面加一对空花括号,用于初始化基类子对象即可:
// 第一个{}对应flatbuffers::NativeTable的初始化,后面三个对应三个成员变量 TableKeyT key { {}, std::string(sym), std::string(ex), std::string("") };
方案2:给结构体添加自定义构造函数
如果不想每次初始化都加空括号,可以给TableKeyT添加自定义构造函数,自动处理基类初始化逻辑:
struct TableKeyT : public flatbuffers::NativeTable { typedef TableKey TableType; std::string exp{}; std::string type{}; std::string ext{}; // 自定义带参构造函数 TableKeyT(std::string exp_, std::string type_, std::string ext_) : exp(std::move(exp_)), type(std::move(type_)), ext(std::move(ext_)) {} // 保留默认构造函数,适配FlatBuffers的运行时逻辑要求 TableKeyT() = default; };
添加后你原来的初始化代码可以直接正常使用。
方案3:使用FlatBuffers生成构造函数
如果TableKeyT是FlatBuffers工具flatc自动生成的代码,可以在生成代码时添加--gen-object-api参数,生成的T类会自带对应参数的构造函数,你可以直接调用构造函数初始化,不需要手动写聚合初始化列表。
内容的提问来源于stack exchange,提问作者sleep

