Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/en/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
# C++14 Core Language Features

- [Generic Lambdas](./cpp14/00-generic-lambdas.md)
- [Aggregate NSDMI](./cpp14/08-aggregate-nsdmi.md)

# Additional Resources

Expand Down
72 changes: 72 additions & 0 deletions book/en/src/cpp14/08-aggregate-nsdmi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<div align=right>

🌎 [中文] | [English]
</div>

[中文]: ../../cpp14/08-aggregate-nsdmi.html
[English]: ./08-aggregate-nsdmi.html

# Aggregate NSDMI Initialization

C++14 relaxes aggregate restrictions — classes with non-static data member initializers (NSDMI) can still be aggregates

| Book | Video | Code | X |
| --- | --- | --- | --- |
| [cppreference-aggregate_initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp14/08-aggregate-nsdmi.md) | [Video Explanation]() | [Exercise Code](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/08-aggregate-nsdmi-0.cpp) | |


**Why introduced?**

In C++11, a class with any NSDMI (`int x = 0;`) lost its aggregate status, breaking `{}` initialization. C++14 fixes this contradiction

## I. Basic Usage and Scenarios

```cpp
struct Point {
int x = 0; // NSDMI
int y = 0;
};

Point p1{3, 4}; // C++14: aggregate initialization OK
Point p2{1}; // y uses default 0
Point p3{}; // x=0, y=0
```

## II. Real-World Case — Aggregate + NSDMI in the STL

> The MSVC STL uses aggregates with NSDMI internally. The example below cites the vendored [MSVC STL](https://github.com/mcpp-community/d2mcpp/tree/main/msvc-stl) (source: [`msvc-stl/stl/inc/array`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/array#L20-L23))

```cpp
// MSVC STL · msvc-stl/stl/inc/array (abridged)
struct _Iterator_base12_compatible {
_Container_proxy* _Myproxy{};
_Iterator_base12* _Mynextiter{};
};
```

Both members have `{}` default initializers, yet the type participates in iterator base class inheritance and initialization as an aggregate — relying on C++14's NSDMI aggregate relaxation

## III. Notes

- NSDMI values are only used when no initializer is provided
- `{}` initialization values override NSDMI defaults
- Aggregate members must all be public

## IV. Exercise Code

### Exercise Topics

- 0 - [Aggregate NSDMI — Class with Default Members and Aggregate Init](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/08-aggregate-nsdmi-0.cpp)

### Auto-Checker Command

```
d2x checker aggregate-nsdmi
```

## V. Other

- [Discussion Forum](https://forum.d2learn.org/category/20)
- [d2mcpp Tutorial Repository](https://github.com/mcpp-community/d2mcpp)
- [Tutorial Video List](https://space.bilibili.com/65858958/lists/5208246)
- [Tutorial Support Tool - xlings](https://github.com/openxlings/xlings)
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
# C++14核心语言特性

- [泛型 lambda - generic lambdas](./cpp14/00-generic-lambdas.md)
- [聚合 NSDMI - aggregate NSDMI](./cpp14/08-aggregate-nsdmi.md)

# 其他

Expand Down
72 changes: 72 additions & 0 deletions book/src/cpp14/08-aggregate-nsdmi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<div align=right>

🌎 [中文] | [English]
</div>

[中文]: ./08-aggregate-nsdmi.html
[English]: ../en/cpp14/08-aggregate-nsdmi.html

# 聚合初始化与 NSDMI

C++14 放宽了聚合类型的限制: 拥有非静态数据成员初始化器 (NSDMI) 的类仍然可以是聚合, 可以使用 `{}` 初始化

| Book | Video | Code | X |
| --- | --- | --- | --- |
| [cppreference-aggregate_initialization](https://en.cppreference.com/w/cpp/language/aggregate_initialization) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/08-aggregate-nsdmi.md) | [视频解读]() | [练习代码](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/08-aggregate-nsdmi-0.cpp) | |


**为什么引入?**

C++11 中, 只要类有 NSDMI (`int x = 0;`), 它就不再是聚合, `{}` 初始化失效。这导致给简单数据结构加默认值后反而不能用简洁的聚合初始化。C++14 修复了这个矛盾

## 一、基础用法和场景

```cpp
struct Point {
int x = 0; // NSDMI
int y = 0;
};

Point p1{3, 4}; // C++14: OK, 聚合初始化
Point p2{1}; // y 使用默认值 0
Point p3{}; // x=0, y=0
```

## 二、真实案例 - STL 中的聚合 + NSDMI

> MSVC STL 内部大量使用带 NSDMI 的聚合类型。下面以仓库内置的 [MSVC STL](https://github.com/mcpp-community/d2mcpp/tree/main/msvc-stl) 为例 (源码: [`msvc-stl/stl/inc/array`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/array#L20-L23))

```cpp
// MSVC STL · msvc-stl/stl/inc/array (有删节)
struct _Iterator_base12_compatible {
_Container_proxy* _Myproxy{};
_Iterator_base12* _Mynextiter{};
};
```

两个成员都有 `{}` 默认初始化, 但该类型仍以聚合形式参与迭代器基类的多重继承和初始化, 依赖的正是 C++14 对聚合 NSDMI 的放宽

## 三、注意事项

- NSDMI 的值只在没有提供对应初始化器时使用
- `{}` 初始化的值会覆盖 NSDMI 默认值
- 聚合的成员必须全部为 public

## 四、练习代码

### 练习代码主题

- 0 - [聚合 NSDMI — 带默认成员的类聚合初始化](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/08-aggregate-nsdmi-0.cpp)

### 练习代码自动检测命令

```
d2x checker aggregate-nsdmi
```

## 五、其他

- [交流讨论](https://forum.d2learn.org/category/20)
- [d2mcpp教程仓库](https://github.com/mcpp-community/d2mcpp)
- [教程视频列表](https://space.bilibili.com/65858958/lists/5208246)
- [教程支持工具-xlings](https://github.com/openxlings/xlings)
44 changes: 44 additions & 0 deletions dslings/cpp14/08-aggregate-nsdmi-0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// file: dslings/cpp14/08-aggregate-nsdmi-0.cpp
//
// Exercise/练习: cpp14 | 08 - aggregate NSDMI | 聚合 + 默认成员初始化
//
// Tips/提示:
// - C++14 允许带 NSDMI 的类保持聚合身份
// - 聚合初始化时提供的值覆盖默认值, 未提供的使用 NSDMI 默认值
//
// Docs/文档:
// - https://en.cppreference.com/w/cpp/language/aggregate_initialization
// - https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/08-aggregate-nsdmi.md
//
// 练习交流讨论: http://forum.d2learn.org/category/20
//
// Auto-Checker/自动检测命令:
//
// d2x checker aggregate-nsdmi
//

#include <d2x/cpp/common.hpp>

struct Vec3 {
float x = 0.0f;
D2X_YOUR_ANSWER y = 0.0f;
float z = 0.0f;
};

int main() {

Vec3 v1{1.0f, 2.0f, 3.0f};
d2x_assert_eq(v1.x, 1.0f);
d2x_assert_eq(v1.z, 3.0f);

Vec3 v2{4.0f, D2X_YOUR_ANSWER};
d2x_assert_eq(v2.x, 4.0f);
d2x_assert_eq(v2.y, 5.0f);
d2x_assert_eq(v2.z, D2X_YOUR_ANSWER);

D2X_WAIT

return 0;
}
6 changes: 6 additions & 0 deletions dslings/cpp14/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ target("cpp14-00-generic-lambdas-0")
target("cpp14-00-generic-lambdas-1")
set_kind("binary")
add_files("00-generic-lambdas-1.cpp")

-- target: cpp14-08-aggregate-nsdmi

target("cpp14-08-aggregate-nsdmi-0")
set_kind("binary")
add_files("08-aggregate-nsdmi-0.cpp")
45 changes: 45 additions & 0 deletions dslings/en/cpp14/08-aggregate-nsdmi-0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// file: dslings/en/cpp14/08-aggregate-nsdmi-0.cpp
//
// Exercise: cpp14 | 08 - aggregate NSDMI | aggregate + default member init
//
// Tips:
// - C++14 allows classes with NSDMI to remain aggregates
// - Values provided in aggregate init override defaults; missing values
// use NSDMI defaults
//
// Docs:
// - https://en.cppreference.com/w/cpp/language/aggregate_initialization
// - https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp14/08-aggregate-nsdmi.md
//
// Discussion Forum: http://forum.d2learn.org/category/20
//
// Auto-Checker:
//
// d2x checker aggregate-nsdmi
//

#include <d2x/cpp/common.hpp>

struct Vec3 {
float x = 0.0f;
D2X_YOUR_ANSWER y = 0.0f;
float z = 0.0f;
};

int main() {

Vec3 v1{1.0f, 2.0f, 3.0f};
d2x_assert_eq(v1.x, 1.0f);
d2x_assert_eq(v1.z, 3.0f);

Vec3 v2{4.0f, D2X_YOUR_ANSWER};
d2x_assert_eq(v2.x, 4.0f);
d2x_assert_eq(v2.y, 5.0f);
d2x_assert_eq(v2.z, D2X_YOUR_ANSWER);

D2X_WAIT

return 0;
}
6 changes: 6 additions & 0 deletions dslings/en/cpp14/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ target("cpp14-00-generic-lambdas-0")
target("cpp14-00-generic-lambdas-1")
set_kind("binary")
add_files("00-generic-lambdas-1.cpp")

-- target: cpp14-08-aggregate-nsdmi

target("cpp14-08-aggregate-nsdmi-0")
set_kind("binary")
add_files("08-aggregate-nsdmi-0.cpp")
29 changes: 29 additions & 0 deletions solutions/cpp14/08-aggregate-nsdmi-0.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// d2mcpp: https://github.com/mcpp-community/d2mcpp
// license: Apache-2.0
// reference solution for: dslings/cpp14/08-aggregate-nsdmi-0.cpp
//
// 用途: 仅给 CI 与维护者参考使用,不是教程入口。
// 教程练习入口: dslings/cpp14/08-aggregate-nsdmi-0.cpp
//

#include <d2x/cpp/common.hpp>

struct Vec3 {
float x = 0.0f;
float y = 0.0f;
float z = 0.0f;
};

int main() {

Vec3 v1{1.0f, 2.0f, 3.0f};
d2x_assert_eq(v1.x, 1.0f);
d2x_assert_eq(v1.z, 3.0f);

Vec3 v2{4.0f, 5.0f};
d2x_assert_eq(v2.x, 4.0f);
d2x_assert_eq(v2.y, 5.0f);
d2x_assert_eq(v2.z, 0.0f);

return 0;
}
6 changes: 6 additions & 0 deletions solutions/cpp14/xmake.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@ target("cpp14-00-generic-lambdas-0-ref")
target("cpp14-00-generic-lambdas-1-ref")
set_kind("binary")
add_files("00-generic-lambdas-1.cpp")

-- target: cpp14-08-aggregate-nsdmi

target("cpp14-08-aggregate-nsdmi-0-ref")
set_kind("binary")
add_files("08-aggregate-nsdmi-0.cpp")
Loading