成员类型相同但声明顺序不同的结构体,列表初始化赋值差异问询
结构体成员顺序导致列表初始化赋值失败的原因
示例代码
#include <cstdint> enum struct option_t : uint8_t { INVALID = 0, RESERVED = 1, TEST_OPTION = 2 }; struct Trace_1 { option_t option {option_t::INVALID}; uint32_t iter {0}; }; struct Trace_2 { uint32_t iter {0}; option_t option {option_t::INVALID}; }; int main() { Trace_1 trace1{}; Trace_2 trace2{}; trace2 = {0}; trace1 = {0}; // 编译失败 }
编译报错信息
<source>:32:12: error: no viable overloaded '=' trace1 = {0}; ~~~~~~ ^ ~~~ <source>:15:8: note: candidate function (the implicit copy assignment operator) not viable: cannot convert initializer list argument to 'const Trace_1' struct Trace_1 ^ <source>:15:8: note: candidate function (the implicit move assignment operator) not viable: cannot convert initializer list argument to 'Trace_1' struct Trace_1
原因分析
核心问题出在强类型枚举的隐式转换限制和聚合初始化的成员匹配规则:
- 执行
trace = {0}时,编译器会先尝试用{0}构造对应结构体的临时对象,再通过赋值运算符完成赋值。 - 对于
Trace_2:第一个成员是uint32_t,0可以直接隐式转换为该类型;第二个成员option_t会被自动值初始化(使用默认的option_t::INVALID),临时对象能正常构造,因此赋值合法。 - 对于
Trace_1:第一个成员是强类型枚举option_t。C++标准明确规定,强类型枚举(enum struct/enum class)不允许整数到枚举的隐式转换——必须通过显式转换(如option_t(0))才能完成。而初始化列表中的0是int类型,无法隐式转换为option_t,导致Trace_1临时对象无法构造,赋值操作找不到可行的重载运算符,最终编译报错。
内容的提问来源于stack exchange,提问作者Liu Nick
相关产品推荐
相关产品推荐

