我有一个与下面的代码片段非常相似的代码:
#include <vector>
struct dummy
{
std::vector<int> const data;
dummy() = default;
};
大多数编译器都毫无问题地接受此代码,除了 9 至 14 版本的
clang
表示:
警告:显式默认的默认构造函数被隐式删除 [-Wdefaulted-function-deleted]
注意:“dummy”的默认构造函数被隐式删除,因为 const 限定类型“const std::vector”的字段“data”不会被初始化
在
clang 15
中,问题再次消失。
直播
注意,如果删除
const
,错误也会消失。
但是我希望
data
被初始化为 const
空向量。
这是一个
clang
错误吗?否则,为什么这段代码被拒绝(为什么其他编译器不抱怨)?
在解决 CWG 2394 之前,默认的默认构造函数被定义为已删除(如果有)
const
没有默认初始值设定项的类类型的非静态成员没有用户提供的默认构造函数。
此规则的目的是避免出现以下情况:您默认将对象初始化为不确定状态,然后不可能将其修改为任何可用状态,这只能是错误的。
但是,这个条件并没有完全实现这一点,DR 通过提出与
const
变量声明相同的要求来解决它,它正确地认为即使是非用户提供的默认构造函数也可以正确初始化。
现在的问题是 libstdc++ 通过默认它来实现
std::vector
的默认构造函数(参见例如 github镜像)。结果是默认构造函数不是由用户提供。
在 P0490 中的 NB 注释 RU1 决议之前(即 CWG 2394 决议之前),
const
类型的变量声明本身对用户提供的默认构造函数具有相同的限制,但在决议之后,std::vector::vector()
的实现默认是有效的,因为容器要求只要求变量声明const std::vector<int> data;
格式良好,这是通过 NB 注释解决的。
因此,在尚未实现缺陷报告的 Clang 版本中以及使用 libstdc++ 时,它将失败。
我还没有检查过,但旧版本的 Clang 可能使用旧的 libstdc++ 版本,其中默认构造函数尚未以这种方式实现。 (请参阅 2018 年的 GCC 提交 https://github.com/gcc-mirror/gcc/commit/e6cad9872b098f50aefb39019b6b1ba74d8c6c07)