VS切换至C++20后,初始化列表转结构体失败的编译问题
为什么显式默认拷贝构造函数会导致C++20中聚合初始化失败?
你的代码问题根源在于C++20修改了聚合类型的判定规则,具体细节如下:
问题核心
在C++17及更早版本中,显式默认的拷贝构造函数(foo(const foo&) = default;)不会影响foo作为聚合类型的判定,所以foo{'a'}会触发聚合初始化,直接给成员a赋值。
但C++20的标准里,任何用户声明的构造函数(包括显式默认或删除的特殊成员函数)都会让类型不再属于聚合类型。你的foo因为声明了拷贝构造函数,不再是聚合类型,此时foo{'a'}这种列表初始化会尝试寻找匹配的构造函数——而你的foo既没有接受char的构造函数,也没有能适配初始化列表的构造函数,因此编译器报错"无法从初始化列表转换为foo"。
解决办法
根据你的需求,可以选择以下几种方案:
删除显式默认的拷贝构造函数
如果你没有特殊需求(比如需要抑制移动构造或其他场景),编译器会自动生成默认的拷贝构造函数,此时foo恢复为聚合类型,foo{'a'}的聚合初始化就能正常工作。添加显式构造函数支持列表初始化
如果你必须保留显式默认的拷贝构造函数,可以手动添加一个接受char的构造函数,让初始化列表能匹配上:struct foo { foo(const foo&) = default; foo(char c) : a(c) {} // 显式构造函数适配char类型 char a; };使用指定成员的聚合初始化(仅当类型为聚合时可用)
若删除拷贝构造函数让foo回到聚合类型,也可以用更清晰的成员指定语法完成初始化:foo f{.a = 'a'};
内容的提问来源于stack exchange,提问作者pepece
相关产品推荐
相关产品推荐

