You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs(cpp11): add STL real-world case, exercise mapping, and tagged-union exercise for 16-generalized-unions (mcpp-community#57)
* docs(cpp11): add STL real-world case and exercise mapping for 16-generalized-unions
- add section 二 真实案例 — include std::variant _Variant_storage_ and
std::any _Storage_t examples, both cited from vendored msvc-stl/
- fill in 四 练习代码 — exercise descriptions, file links and
d2x checker command
- fix empty Code link in header table
Case selection notes:
Picked _Variant_storage_ over std::optional _Optional_destruct_base
because the variant recursive union demonstrates both key C++11
generalized-union capabilities — non-trivial members and manual
destructor management — while the optional pattern is effectively
a special case of variant. std::any adds a second typical use:
union as type-erased storage. Both are directly traceable in the
vendored msvc-stl/, consistent with how ch00 cites xutility.
* docs(cpp11): fix exercise list format to match project convention
* Potential fix for pull request finding
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
* docs(cpp11): apply Copilot review suggestions — remove inaccurate noexcept, fix 类型安全 wording
* feat(cpp11): add tagged-union exercise for 16-generalized-unions
Add exercise 2 — tagged/discriminated union combining enum tag + union
to implement a simplified std::variant-like Value type.
Exercise progression:
0. union default member initialization (static rule)
1. non-trivial type + placement new + manual destructor
2. enum tag + union → type-safe discriminated union
Design rationale:
ex 2 ties ex 0 and ex 1 together by adding a tag enum to track
the active member — the exact pattern used by std::variant's
internal _Variant_storage_, directly echoing the STL real-world
case in the chapter. Learners construct/destruct/switch members
based on tag, covering all three C++11 generalized-union
capabilities in one practical exercise.
* docs(cpp11): sync en book chapter with zh for 16-generalized-unions
Apply the same updates to the English book chapter:
- add section II Real-World Case (msvc-stl variant + any examples)
- fill in section IV Exercise Code (exercise links + d2x checker command)
- fix empty Code link in header table
- add ex2 tagged-union exercise link
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
> Using the `std::variant` implementation from the vendored [MSVCSTL](https://github.com/mcpp-community/d2mcpp/tree/main/msvc-stl) as an example (source: [`msvc-stl/stl/inc/variant`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/variant#L343-L399)), `_CONSTEXPR20` / `_STD` are internal macros and can be ignored while reading
134
+
135
+
```cpp
136
+
// MSVC STL · msvc-stl/stl/inc/variant (abridged)
137
+
template <class_First, class... _Rest>
138
+
class _Variant_storage_<false, _First, _Rest...> {
139
+
public:
140
+
union {
141
+
remove_cv_t<_First> _Head;
142
+
_Variant_storage<_Rest...> _Tail;
143
+
};
144
+
145
+
_CONSTEXPR20 ~_Variant_storage_() {
146
+
// The union does not know which member is active; destruction is
147
+
// controlled by the outer variant class
148
+
}
149
+
// ...
150
+
};
151
+
```
152
+
153
+
`std::variant` uses a recursive union to hold multiple types in a single block of memory. The non-trivial destructor variant must explicitly define the destructor — this is exactly the key capability of C++11 generalized unions: unions can contain members with non-trivial special member functions, but their lifecycle must be managed manually
154
+
155
+
**std::any Small-Object Optimization — Union as Type-Erased Storage**
156
+
> `std::any` uses a union to combine small-object storage, heap pointers, and raw byte buffers into the same memory (source: [`msvc-stl/stl/inc/any`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/any#L362-L376))
> Summary: The core storage of both `std::variant` and `std::any` relies on generalized unions. Before C++11, unions could only hold POD types, forcing the standard library to use raw byte buffers + placement new as a workaround. Generalized unions allow code to directly express "one-of-many" memory layout, with an outer wrapper responsible for tracking the active member and managing its lifecycle, making the code easier to maintain
178
+
179
+
## III. Precautions
131
180
132
181
**Accessibility**
133
182
@@ -171,11 +220,21 @@ m.a = 1;
171
220
double c = m.b; // Error: undefined behavior.
172
221
```
173
222
174
-
## III. Exercise Code
223
+
## IV. Exercise Code
224
+
225
+
### Exercise Code Topics
175
226
176
-
TODO
227
+
- 0 - [Union Default Member Initialization](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp11/16-generalized-unions-0.cpp)
228
+
- 1 - [Union with Non-Trivial Types and Lifecycle Management](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp11/16-generalized-unions-1.cpp)
229
+
- 2 - [Tagged Discriminated Union — A Simplified std::variant with enum + union](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp11/16-generalized-unions-2.cpp)
0 commit comments