`std::default_initializable` 和 `std::is_default_constructible` 有什么区别?

Hol*_*Cat 14 c++ c++20

C++20 添加了一个名为std::default_initializable. 命名上的差异std::is_default_constructible似乎太明显了,不可能是偶然的。

他们的规范也有不同的措辞(至少在 cppreference 上),但是我不明白有效的差异是什么。

以下是 cppreference 文章的简短摘要:

std::is_default_constructible<T>要求T foo();格式正确,并假设它不会被解析为函数声明。换句话说(如果我理解正确的话),T需要是可破坏的, T()需要是良好的。
(编辑:它似乎不需要可破坏性,所以这是第一个区别)

std::default_initializable,另一方面,需要T foo;,T()T{}都是良构的。

这两者之间有什么有效的区别吗?

据我所知,T{}总是被解释为T()(忽略最烦人的解析,这里不算数),所以我不确定为什么明确提到它。此外T()福祉形成似乎暗示T foo;福祉形成。

Bar*_*rry 7

这基本上是LWG 3149

DefaultConstructible<T>相当于Constructible<T>(18.4.11 [concept.constructible]),相当于is_constructible_v<T>(20.15.4.3 [meta.unary.prop])。根据 20.15.4.3 [meta.unary.prop] 第 8 段:

is_­constructible<T, Args...>当且仅当以下变量定义对于某些发明的变量 t 格式良好时,才满足模板特化的谓词条件:

T t(declval<Args>()...);
Run Code Online (Sandbox Code Playgroud)

DefaultConstructible<T>要求类型的对象T可以进行值初始化,而不是按预期进行默认初始化

这个概念的动机是检查你是否可以写:

T t;
Run Code Online (Sandbox Code Playgroud)

但是定义不会检查它,它会检查您是否可以编写T(). 但T()也不意味着您可以编写T{}- 有些类型具有不同的含义:

struct S0 { explicit S0() = default; };
struct S1 { S0 x; }; // Note: aggregate
S1 x;   // Ok
S1 y{}; // ill-formed; copy-list-initializes x from {}
Run Code Online (Sandbox Code Playgroud)

目的是为了理智起见,简化图书馆必须处理的事情,因此我们希望拒绝S1只是奇怪。


然后,一旦概念检查出与 不同的内容is_default_constructibleLWG 3338就将其重命名。因为,不同的事物应该有不同的名称。

  • @einpoklum:不,他的意思是“复制列表初始化”,列表初始化的一种特定形式(又名:用“T t = {...};”得到的)。未给定初始值设定项或默认初始值设定项的聚合的任何成员都将[通过空花括号初始化列表中的复制列表初始化进行初始化](https://timsong-cpp.github.io/cppwp/n4659 /dcl.init.aggr#8)。 (2认同)