Skip to content

Commit 834a072

Browse files
committed
copy ctor updted, rule of 3, excpetion
1 parent 72a8a7a commit 834a072

14 files changed

Lines changed: 2360 additions & 506 deletions

CMakeLists.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ add_executable(algorithms_library src/algorithms_library.cpp)
7575

7676
add_executable(vector src/vector.cpp)
7777

78+
add_executable(queue src/queue.cpp)
79+
7880
add_executable(variadic_templates src/variadic_templates.cpp)
7981

8082
add_executable(enum src/enum.cpp)
@@ -225,13 +227,11 @@ add_executable(VTABLE_and_VPTR src/VTABLE_and_VPTR.cpp)
225227

226228
# add_executable(allocator src/allocator.cpp)
227229

228-
add_executable(noexcept_operator_specifier src/noexcept_operator_specifier.cpp)
229-
230230
add_executable(callbacks src/callbacks.cpp)
231231

232232
add_executable(template_specialization_tag_dispatch src/template_specialization_tag_dispatch.cpp)
233233

234-
#add_executable(copy_move src/class/copy_move.cpp)
234+
add_executable(copy_constructor_copy_assignment src/copy_constructor_copy_assignment.cpp)
235235

236236
add_executable(forward src/forward.cpp)
237237

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ This change ensures that VSCode uses the "Ninja Multi-Config" generator by defau
247247
- [Class Forward Declaration](docs/class_forward_declaration.md)
248248
- [Class Constructor Initializationlist](src/class/constructor_initialization_list.cpp)
249249
- [Class Constructor Aggregate/ Copy/ Default/ Direct/ Value/ Uniform/ Zero Initialization, Initializer List](docs/aggregate-copy-default-direct-value-zero_initialization.md)
250-
- [Copy/ Move Constructor, rvalue, lvalue, move semantic](docs/copy_constructor_move_constructor_rvalue_lvalue_move_semantic.md)
250+
- [Copy Constructor, Copy Assignment, Move Constructor, Assignment](docs/copy_constructor_move_constructor.md)
251251
- [Cyclic (Circular) Dependency](docs/circular_dependencies.md)
252252
- [Default(=default), Deleted (=delete) Constructors](docs/default_constructors_=default_0_delete.md)
253253
- [Diamond Problem Virtual Inheritance](src/class/diamond_problem_virtual_inheritance.cpp)
@@ -304,7 +304,7 @@ This change ensures that VSCode uses the "Ninja Multi-Config" generator by defau
304304
- [Pointer to implementation (PIMPL)](docs/PIMPL.md)
305305
- [Return Type Resolver](docs/return_type_resolver.md)
306306
- [Resource Acquisition Is Initialization (RAII)](docs/RAII.md)
307-
- [Rule of 5](docs/rule_of_5.md)
307+
- [Rule of 3, Rule of 5](docs/rule_of_3_rule_of_5.md)
308308
- [Substitution failure is not an error (SFINAE)](docs/SFINAE.md)
309309
- [Stack overflow](docs/stack_overflow.md)
310310
- [Stack Unwinding](docs/stack_unwinding.md)
@@ -318,6 +318,7 @@ This change ensures that VSCode uses the "Ninja Multi-Config" generator by defau
318318
- [Printing List of All Included Headers](docs/print_all_included_headers.md)
319319
- [fPIE (Position Independent Executable) and fPIC(Position Independent Code and) ](docs/fPIE_and_fPIC.md)
320320
- [Lexical Analyzer](docs/lexical_analyzer.md)
321+
- [`std::optional`, `std::variant`, and `std::any`](docs/any_variant_optional.md)
321322

322323
## [Optimizing C++](src/optimizing_cpp)
323324

docs/any_variant_optional.md

Lines changed: 275 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
Below is a **practical, interview-ready mental model** for
2+
`std::optional`, `std::variant`, and `std::any` — focused on **avoiding null pointers** and **expressing absence safely**.
3+
4+
No fluff, no emojis, straight engineering trade-offs.
5+
6+
---
7+
8+
## 1. The core problem they solve
9+
10+
Classic C++ problems:
11+
12+
❌ Returning `nullptr`
13+
❌ Returning invalid sentinel values
14+
❌ Output parameters
15+
❌ Boolean + output value patterns
16+
❌ Implicit assumptions (“this pointer might be null”)
17+
18+
Modern C++ replaces these with **type-level guarantees**.
19+
20+
---
21+
22+
## 2. `std::optional<T>`
23+
24+
### What it expresses
25+
26+
> **A value may or may not exist**
27+
28+
### Think of it as
29+
30+
> A pointer without ownership, allocation, or lifetime issues
31+
32+
### Typical use cases
33+
34+
* Function may fail to produce a value
35+
* Cache lookup
36+
* Optional configuration
37+
* Parsing results
38+
* Lazy initialization
39+
40+
### Example
41+
42+
```cpp
43+
std::optional<int> parseInt(const std::string& s) {
44+
try {
45+
return std::stoi(s);
46+
} catch (...) {
47+
return std::nullopt;
48+
}
49+
}
50+
```
51+
52+
Usage:
53+
54+
```cpp
55+
if (auto v = parseInt("42")) {
56+
std::cout << *v;
57+
}
58+
```
59+
60+
### Why it’s better than a pointer
61+
62+
`int*` → who owns it? is it null?
63+
`std::optional<int>` → explicit absence
64+
65+
### Key properties
66+
67+
* No heap allocation
68+
* Value stored inline
69+
* Checked access
70+
* Forces caller to acknowledge absence
71+
72+
### When NOT to use
73+
74+
* When absence is **impossible**
75+
* When you need multiple alternative types
76+
* When lifetime must be shared
77+
78+
---
79+
80+
## 3. `std::variant<Ts...>`
81+
82+
### What it expresses
83+
84+
> **Exactly one of several known types**
85+
86+
### Think of it as
87+
88+
> A type-safe tagged union
89+
90+
### Typical use cases
91+
92+
* State machines
93+
* Message passing
94+
* AST nodes
95+
* API results with multiple valid forms
96+
* Replacing base-class polymorphism when behavior is simple
97+
98+
### Example
99+
100+
```cpp
101+
using Result = std::variant<int, std::string>;
102+
103+
Result r = 42;
104+
```
105+
106+
Usage:
107+
108+
```cpp
109+
std::visit([](auto&& v) {
110+
std::cout << v;
111+
}, r);
112+
```
113+
114+
### Expressing absence
115+
116+
```cpp
117+
using Result = std::variant<std::monostate, int>;
118+
```
119+
120+
But:
121+
❌ worse than `std::optional<int>`
122+
✅ use `optional` unless absence is one of many states
123+
124+
### Why it’s better than inheritance
125+
126+
❌ virtual dispatch
127+
❌ heap allocation
128+
❌ fragile base classes
129+
130+
✅ compile-time exhaustiveness
131+
✅ no RTTI
132+
✅ no allocation
133+
134+
### Key properties
135+
136+
* One active alternative at a time
137+
* Known set of types
138+
* Compile-time checked handling
139+
140+
### When NOT to use
141+
142+
* Open-ended types
143+
* Plugin systems
144+
* When type list is not stable
145+
146+
---
147+
148+
## 4. `std::any`
149+
150+
### What it expresses
151+
152+
> **Some value of unknown type**
153+
154+
### Think of it as
155+
156+
> Type-erased storage with runtime type checking
157+
158+
### Typical use cases
159+
160+
* Framework internals
161+
* Plugin APIs
162+
* Heterogeneous containers
163+
* Metadata
164+
* Configuration blobs
165+
166+
### Example
167+
168+
```cpp
169+
std::any a = 42;
170+
171+
if (a.type() == typeid(int)) {
172+
int v = std::any_cast<int>(a);
173+
}
174+
```
175+
176+
### Why it’s dangerous
177+
178+
❌ No compile-time guarantees
179+
❌ Runtime errors if misused
180+
❌ Easy to abuse
181+
❌ Slower
182+
183+
### Expressing absence
184+
185+
```cpp
186+
std::any a; // empty
187+
```
188+
189+
But:
190+
❌ unclear intent
191+
❌ no documentation in the type
192+
❌ worse than `optional`
193+
194+
### Rule of thumb
195+
196+
> If you think you need `std::any`, question the design first
197+
198+
---
199+
200+
## 5. Comparison table
201+
202+
| Feature | `optional<T>` | `variant<Ts...>` | `any` |
203+
| ------------------- | ------------- | ---------------- | ---------- |
204+
| Expresses absence | YES | Indirectly | YES (weak) |
205+
| Type safety | Strong | Strong | Weak |
206+
| Compile-time checks | YES | YES | NO |
207+
| Heap allocation | NO | NO | Maybe |
208+
| Intent clarity | Excellent | Excellent | Poor |
209+
| Runtime overhead | Minimal | Minimal | Higher |
210+
| Best for APIs | YES | YES | Rarely |
211+
212+
---
213+
214+
## 6. Avoiding null pointers — best practices
215+
216+
### ❌ Old style
217+
218+
```cpp
219+
Foo* findFoo();
220+
```
221+
222+
### ✅ Modern C++
223+
224+
```cpp
225+
std::optional<Foo> findFoo();
226+
```
227+
228+
or if ownership matters:
229+
230+
```cpp
231+
std::unique_ptr<Foo> findFoo();
232+
```
233+
234+
### Reference rule
235+
236+
If something **must exist**, use:
237+
238+
```cpp
239+
Foo&
240+
```
241+
242+
If it **might not exist**, use:
243+
244+
```cpp
245+
std::optional<std::reference_wrapper<Foo>>
246+
```
247+
248+
---
249+
250+
## 7. Decision guide (memorize this)
251+
252+
### Ask yourself:
253+
254+
1. **Can it be absent?**
255+
`std::optional<T>`
256+
257+
2. **Is it one of a fixed set of types?**
258+
`std::variant<Ts...>`
259+
260+
3. **Is the type unknown or open-ended?**
261+
`std::any` (last resort)
262+
263+
---
264+
265+
## 8. Interview-grade sound bites
266+
267+
You can safely say:
268+
269+
*`std::optional` encodes absence in the type system.”
270+
*`std::variant` gives compile-time checked alternatives without polymorphism.”
271+
*`std::any` trades safety for flexibility and should be isolated.”
272+
* “Null pointers express failure poorly; modern C++ prefers semantic types.”
273+
274+
---
275+

0 commit comments

Comments
 (0)