From 5de0fdeb6f821bce0fd54bb2e6dda9d11ec1fe16 Mon Sep 17 00:00:00 2001
From: li-zhou <2181719471@qq.com>
Date: Tue, 23 Jun 2026 23:10:22 +0800
Subject: [PATCH] feat(cpp14): add 08-aggregate-nsdmi
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Book chapter (zh + en):
- section 一/I: Basic usage — struct with defaults, partial init
- section 二/II: Real-world case — _Iterator_base12_compatible
from msvc-stl/stl/inc/array#L20-L23
- section 三/III: Notes — NSDMI only when no initializer provided
- section 四/IV: Exercise topics and d2x checker command
- section 五/V: External resources
Exercise:
0. Vec3 struct with NSDMI, partial and full aggregate init.
3 D2X_YOUR_ANSWER.
Build wiring:
- register 08 target in dslings/cpp14, dslings/en/cpp14,
solutions/cpp14
- add 08 entry to zh/en SUMMARY.md
---
book/en/src/SUMMARY.md | 1 +
book/en/src/cpp14/08-aggregate-nsdmi.md | 72 +++++++++++++++++++++++
book/src/SUMMARY.md | 1 +
book/src/cpp14/08-aggregate-nsdmi.md | 72 +++++++++++++++++++++++
dslings/cpp14/08-aggregate-nsdmi-0.cpp | 44 ++++++++++++++
dslings/cpp14/xmake.lua | 6 ++
dslings/en/cpp14/08-aggregate-nsdmi-0.cpp | 45 ++++++++++++++
dslings/en/cpp14/xmake.lua | 6 ++
solutions/cpp14/08-aggregate-nsdmi-0.cpp | 29 +++++++++
solutions/cpp14/xmake.lua | 6 ++
10 files changed, 282 insertions(+)
create mode 100644 book/en/src/cpp14/08-aggregate-nsdmi.md
create mode 100644 book/src/cpp14/08-aggregate-nsdmi.md
create mode 100644 dslings/cpp14/08-aggregate-nsdmi-0.cpp
create mode 100644 dslings/en/cpp14/08-aggregate-nsdmi-0.cpp
create mode 100644 solutions/cpp14/08-aggregate-nsdmi-0.cpp
diff --git a/book/en/src/SUMMARY.md b/book/en/src/SUMMARY.md
index b2008be..2a8581f 100644
--- a/book/en/src/SUMMARY.md
+++ b/book/en/src/SUMMARY.md
@@ -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
diff --git a/book/en/src/cpp14/08-aggregate-nsdmi.md b/book/en/src/cpp14/08-aggregate-nsdmi.md
new file mode 100644
index 0000000..c2ad002
--- /dev/null
+++ b/book/en/src/cpp14/08-aggregate-nsdmi.md
@@ -0,0 +1,72 @@
+
+
+ 🌎 [中文] | [English]
+
+
+[中文]: ../../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)
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 7efe83a..053e273 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -31,6 +31,7 @@
# C++14核心语言特性
- [泛型 lambda - generic lambdas](./cpp14/00-generic-lambdas.md)
+- [聚合 NSDMI - aggregate NSDMI](./cpp14/08-aggregate-nsdmi.md)
# 其他
diff --git a/book/src/cpp14/08-aggregate-nsdmi.md b/book/src/cpp14/08-aggregate-nsdmi.md
new file mode 100644
index 0000000..0a0c7a0
--- /dev/null
+++ b/book/src/cpp14/08-aggregate-nsdmi.md
@@ -0,0 +1,72 @@
+
+
+ 🌎 [中文] | [English]
+
+
+[中文]: ./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)
diff --git a/dslings/cpp14/08-aggregate-nsdmi-0.cpp b/dslings/cpp14/08-aggregate-nsdmi-0.cpp
new file mode 100644
index 0000000..355a702
--- /dev/null
+++ b/dslings/cpp14/08-aggregate-nsdmi-0.cpp
@@ -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
+
+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;
+}
diff --git a/dslings/cpp14/xmake.lua b/dslings/cpp14/xmake.lua
index 8a21cbf..6ea44c5 100644
--- a/dslings/cpp14/xmake.lua
+++ b/dslings/cpp14/xmake.lua
@@ -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")
diff --git a/dslings/en/cpp14/08-aggregate-nsdmi-0.cpp b/dslings/en/cpp14/08-aggregate-nsdmi-0.cpp
new file mode 100644
index 0000000..17d549a
--- /dev/null
+++ b/dslings/en/cpp14/08-aggregate-nsdmi-0.cpp
@@ -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
+
+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;
+}
diff --git a/dslings/en/cpp14/xmake.lua b/dslings/en/cpp14/xmake.lua
index 8a21cbf..6ea44c5 100644
--- a/dslings/en/cpp14/xmake.lua
+++ b/dslings/en/cpp14/xmake.lua
@@ -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")
diff --git a/solutions/cpp14/08-aggregate-nsdmi-0.cpp b/solutions/cpp14/08-aggregate-nsdmi-0.cpp
new file mode 100644
index 0000000..7a2b602
--- /dev/null
+++ b/solutions/cpp14/08-aggregate-nsdmi-0.cpp
@@ -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
+
+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;
+}
diff --git a/solutions/cpp14/xmake.lua b/solutions/cpp14/xmake.lua
index 8bbbb90..9c406a4 100644
--- a/solutions/cpp14/xmake.lua
+++ b/solutions/cpp14/xmake.lua
@@ -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")