Skip to content

Commit

Permalink
增加适用范围描述
Browse files Browse the repository at this point in the history
  • Loading branch information
Matrix-A authored Jan 2, 2024
1 parent 69d75bb commit b2fd4a8
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/群友提交/第10题/Matrix-A.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,51 @@ void for_each_member(const T& agg, Fn&& fn) {
}
}

/*
T 类型的对象的列表初始化的效果是:
1. 如果花括号初始化列表 包含指派初始化器列表,并且 T 不是引用类型,那么 T 必须是聚合类。由指派初始化器列表中的指派符组成的标识符序列必须是 T 的非静态数据成员组成的标识符序列的子序列。进行聚合初始化。
(C++20 起)
2. 如果 T 是聚合类且花括号初始化列表 在不含指派初始化器列表的情况下(C++20 起)拥有单个(可有 cv 限定的)相同类型或派生类型的元素,那么从该元素初始化对象(对于复制列表初始化为复制初始化,对于直接列表初始化为直接初始化)。
3. 否则,如果 T 是字符数组且初始化列表拥有单个类型适当的字符串字面量元素,那么照常从字符串字面量初始化数组。
4. 否则,如果 T 是聚合类型,那么进行聚合初始化。
5. 否则,如果花括号初始化列表 列表为空,且 T 是拥有默认构造函数的类类型,那么进行值初始化。
6. 否则,如果 T 是 std::initializer_list 的特化,那么该 T 对象会以如下方式初始化。
7. 否则,以两个阶段考虑 T 的构造函数:
7.1 检验所有接受 std::initializer_list 作为它的唯一实参,或如果剩余实参都具有默认值则为它的首个实参的构造函数,并通过重载决议与单个 std::initializer_list 类型的实参进行匹配。
7.2 如果上一个阶段未产生匹配,那么 T 的所有构造函数都参与针对由花括号初始化列表 的各元素所组成的实参集的重载决议,它会受到只允许非窄化转换的限制。如果这个阶段为复制列表初始化产生的最佳匹配是 explicit 构造函数,那么编译失败(注意:简单复制初始化中完全不考虑 explicit 构造函数)。
...
*/

/*
* 使用 { { detail::Anything{} } ... } 初始化成员的匹配顺序:
* 1. 不适用,无指派初始化器
* 2. 适用
* 3. 不适用
* 4. 适用,聚合初始化(如果为空类,会产生初始化失败,因为参数个数1,需要参数个数为0)
* 5. 不适用,花括号初始化列表不为空
* 6. 适用
* 7.1 适用,优先考虑接受 std::initializer_list 作为它的唯一实参的构造函数
* 7.2 适用,优先匹配到复制构造或移动构造,如果存在
* 其他:不可能到后续匹配
*/

/*
* 因此聚合类成员的适用范围
* 1. 基础类型
* 2. 聚合类型
* 3. 非聚合类型,但是拥有接受 std::initializer_list 作为它的唯一实参的构造函数
* 4. 非聚合类型,不存在接受 std::initializer_list 作为它的唯一实参的构造函数,但存在移动或复制构造函数,且不存在其他接受单一实参的构造函数
*/

/*
* 注: 适用 mqb方案 表示使用 { detail::Anything{}... } 初始化成员
*
* 已知特殊情况
* 1. 成员为空类且聚合类型对象,不适用,因为参数过多(mqb方案适用这种情况,因为会直接转为对应的对象)
* 2. 存在空基类的聚合类型对象,不适用,因为基类需要一个"{}"进行初始化(mqb方案也不使用,存在一个Anything用于初始化基类)(详见花括号消除)
*/

int main() {
auto print = [](const auto& member) {
if constexpr (!requires { std::cout << member; }) {
Expand Down

0 comments on commit b2fd4a8

Please sign in to comment.