opencode-skills-antigravity 1.0.9 → 1.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/cpp-pro/references/build-tooling.md +440 -0
- package/bundled-skills/cpp-pro/references/concurrency.md +437 -0
- package/bundled-skills/cpp-pro/references/memory-performance.md +397 -0
- package/bundled-skills/cpp-pro/references/modern-cpp.md +304 -0
- package/bundled-skills/cpp-pro/references/templates.md +357 -0
- package/bundled-skills/cpp-pro/resources/implementation-playbook.md +43 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +4 -4
- package/bundled-skills/docs/integrations/jetski-gemini-loader/{loader.ts → loader.mjs} +38 -50
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-15.csv +1 -1
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-15.md +1 -1
- package/bundled-skills/docs/maintainers/security-findings-triage-2026-03-18-addendum.md +1 -1
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/agent-overload-recovery.md +54 -0
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/faq.md +8 -0
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +4 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +5 -5
- package/bundled-skills/docs/users/visual-guide.md +4 -4
- package/bundled-skills/gdb-cli/SKILL.md +239 -0
- package/bundled-skills/jobgpt/SKILL.md +100 -0
- package/bundled-skills/moyu/SKILL.md +267 -0
- package/bundled-skills/windows-shell-reliability/SKILL.md +107 -0
- package/package.json +1 -1
- package/bundled-skills/goldrush-api/SKILL.md +0 -109
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# Memory Management & Performance
|
|
2
|
+
|
|
3
|
+
## Smart Pointers
|
|
4
|
+
|
|
5
|
+
```cpp
|
|
6
|
+
#include <memory>
|
|
7
|
+
|
|
8
|
+
// unique_ptr - exclusive ownership
|
|
9
|
+
auto create_resource() {
|
|
10
|
+
return std::make_unique<Resource>("data");
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// shared_ptr - reference counting
|
|
14
|
+
std::shared_ptr<Data> shared = std::make_shared<Data>(42);
|
|
15
|
+
std::weak_ptr<Data> weak = shared; // Non-owning reference
|
|
16
|
+
|
|
17
|
+
// Custom deleters
|
|
18
|
+
auto file_deleter = [](FILE* fp) { if (fp) fclose(fp); };
|
|
19
|
+
std::unique_ptr<FILE, decltype(file_deleter)> file(
|
|
20
|
+
fopen("data.txt", "r"),
|
|
21
|
+
file_deleter
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// enable_shared_from_this
|
|
25
|
+
class Node : public std::enable_shared_from_this<Node> {
|
|
26
|
+
public:
|
|
27
|
+
std::shared_ptr<Node> get_shared() {
|
|
28
|
+
return shared_from_this();
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Custom Allocators
|
|
34
|
+
|
|
35
|
+
```cpp
|
|
36
|
+
#include <memory>
|
|
37
|
+
#include <vector>
|
|
38
|
+
|
|
39
|
+
// Pool allocator for fixed-size objects
|
|
40
|
+
template<typename T, size_t PoolSize = 1024>
|
|
41
|
+
class PoolAllocator {
|
|
42
|
+
struct Block {
|
|
43
|
+
alignas(T) std::byte data[sizeof(T)];
|
|
44
|
+
Block* next;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
Block pool_[PoolSize];
|
|
48
|
+
Block* free_list_ = nullptr;
|
|
49
|
+
|
|
50
|
+
public:
|
|
51
|
+
using value_type = T;
|
|
52
|
+
|
|
53
|
+
PoolAllocator() {
|
|
54
|
+
// Initialize free list
|
|
55
|
+
for (size_t i = 0; i < PoolSize - 1; ++i) {
|
|
56
|
+
pool_[i].next = &pool_[i + 1];
|
|
57
|
+
}
|
|
58
|
+
pool_[PoolSize - 1].next = nullptr;
|
|
59
|
+
free_list_ = &pool_[0];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
T* allocate(size_t n) {
|
|
63
|
+
if (n != 1 || !free_list_) {
|
|
64
|
+
throw std::bad_alloc();
|
|
65
|
+
}
|
|
66
|
+
Block* block = free_list_;
|
|
67
|
+
free_list_ = free_list_->next;
|
|
68
|
+
return reinterpret_cast<T*>(block->data);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void deallocate(T* p, size_t n) {
|
|
72
|
+
if (n != 1) return;
|
|
73
|
+
Block* block = reinterpret_cast<Block*>(p);
|
|
74
|
+
block->next = free_list_;
|
|
75
|
+
free_list_ = block;
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Usage
|
|
80
|
+
std::vector<int, PoolAllocator<int>> vec;
|
|
81
|
+
|
|
82
|
+
// Arena allocator - bump allocator
|
|
83
|
+
class Arena {
|
|
84
|
+
std::byte* buffer_;
|
|
85
|
+
size_t size_;
|
|
86
|
+
size_t offset_ = 0;
|
|
87
|
+
|
|
88
|
+
public:
|
|
89
|
+
Arena(size_t size) : size_(size) {
|
|
90
|
+
buffer_ = new std::byte[size];
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
~Arena() {
|
|
94
|
+
delete[] buffer_;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
template<typename T>
|
|
98
|
+
T* allocate(size_t n = 1) {
|
|
99
|
+
size_t alignment = alignof(T);
|
|
100
|
+
size_t space = size_ - offset_;
|
|
101
|
+
void* ptr = buffer_ + offset_;
|
|
102
|
+
|
|
103
|
+
if (std::align(alignment, sizeof(T) * n, ptr, space)) {
|
|
104
|
+
offset_ = size_ - space + sizeof(T) * n;
|
|
105
|
+
return static_cast<T*>(ptr);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
throw std::bad_alloc();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
void reset() {
|
|
112
|
+
offset_ = 0;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Move Semantics
|
|
118
|
+
|
|
119
|
+
```cpp
|
|
120
|
+
#include <utility>
|
|
121
|
+
#include <algorithm>
|
|
122
|
+
|
|
123
|
+
class Buffer {
|
|
124
|
+
size_t size_;
|
|
125
|
+
char* data_;
|
|
126
|
+
|
|
127
|
+
public:
|
|
128
|
+
// Constructor
|
|
129
|
+
Buffer(size_t size) : size_(size), data_(new char[size]) {}
|
|
130
|
+
|
|
131
|
+
// Destructor
|
|
132
|
+
~Buffer() { delete[] data_; }
|
|
133
|
+
|
|
134
|
+
// Copy constructor
|
|
135
|
+
Buffer(const Buffer& other) : size_(other.size_), data_(new char[size_]) {
|
|
136
|
+
std::copy(other.data_, other.data_ + size_, data_);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Copy assignment
|
|
140
|
+
Buffer& operator=(const Buffer& other) {
|
|
141
|
+
if (this != &other) {
|
|
142
|
+
delete[] data_;
|
|
143
|
+
size_ = other.size_;
|
|
144
|
+
data_ = new char[size_];
|
|
145
|
+
std::copy(other.data_, other.data_ + size_, data_);
|
|
146
|
+
}
|
|
147
|
+
return *this;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Move constructor
|
|
151
|
+
Buffer(Buffer&& other) noexcept
|
|
152
|
+
: size_(other.size_), data_(other.data_) {
|
|
153
|
+
other.size_ = 0;
|
|
154
|
+
other.data_ = nullptr;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Move assignment
|
|
158
|
+
Buffer& operator=(Buffer&& other) noexcept {
|
|
159
|
+
if (this != &other) {
|
|
160
|
+
delete[] data_;
|
|
161
|
+
size_ = other.size_;
|
|
162
|
+
data_ = other.data_;
|
|
163
|
+
other.size_ = 0;
|
|
164
|
+
other.data_ = nullptr;
|
|
165
|
+
}
|
|
166
|
+
return *this;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Perfect forwarding
|
|
171
|
+
template<typename T>
|
|
172
|
+
void wrapper(T&& arg) {
|
|
173
|
+
process(std::forward<T>(arg)); // Preserves lvalue/rvalue
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## SIMD Optimization
|
|
178
|
+
|
|
179
|
+
```cpp
|
|
180
|
+
#include <immintrin.h> // AVX/AVX2
|
|
181
|
+
#include <cstring>
|
|
182
|
+
|
|
183
|
+
// Vectorized sum using AVX2
|
|
184
|
+
float simd_sum(const float* data, size_t size) {
|
|
185
|
+
__m256 sum_vec = _mm256_setzero_ps();
|
|
186
|
+
|
|
187
|
+
size_t i = 0;
|
|
188
|
+
// Process 8 floats at a time
|
|
189
|
+
for (; i + 8 <= size; i += 8) {
|
|
190
|
+
__m256 vec = _mm256_loadu_ps(&data[i]);
|
|
191
|
+
sum_vec = _mm256_add_ps(sum_vec, vec);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Horizontal sum
|
|
195
|
+
alignas(32) float temp[8];
|
|
196
|
+
_mm256_store_ps(temp, sum_vec);
|
|
197
|
+
float result = 0.0f;
|
|
198
|
+
for (int j = 0; j < 8; ++j) {
|
|
199
|
+
result += temp[j];
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Handle remaining elements
|
|
203
|
+
for (; i < size; ++i) {
|
|
204
|
+
result += data[i];
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Vectorized multiply-add
|
|
211
|
+
void fma_operation(float* result, const float* a, const float* b,
|
|
212
|
+
const float* c, size_t size) {
|
|
213
|
+
for (size_t i = 0; i + 8 <= size; i += 8) {
|
|
214
|
+
__m256 va = _mm256_loadu_ps(&a[i]);
|
|
215
|
+
__m256 vb = _mm256_loadu_ps(&b[i]);
|
|
216
|
+
__m256 vc = _mm256_loadu_ps(&c[i]);
|
|
217
|
+
|
|
218
|
+
// result[i] = a[i] * b[i] + c[i]
|
|
219
|
+
__m256 vr = _mm256_fmadd_ps(va, vb, vc);
|
|
220
|
+
_mm256_storeu_ps(&result[i], vr);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Cache-Friendly Design
|
|
226
|
+
|
|
227
|
+
```cpp
|
|
228
|
+
// Structure of Arrays (SoA) - better cache locality
|
|
229
|
+
struct ParticlesAoS {
|
|
230
|
+
struct Particle {
|
|
231
|
+
float x, y, z;
|
|
232
|
+
float vx, vy, vz;
|
|
233
|
+
};
|
|
234
|
+
std::vector<Particle> particles;
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
struct ParticlesSoA {
|
|
238
|
+
std::vector<float> x, y, z;
|
|
239
|
+
std::vector<float> vx, vy, vz;
|
|
240
|
+
|
|
241
|
+
void update_positions(float dt) {
|
|
242
|
+
// All x coordinates are contiguous - better cache usage
|
|
243
|
+
for (size_t i = 0; i < x.size(); ++i) {
|
|
244
|
+
x[i] += vx[i] * dt;
|
|
245
|
+
y[i] += vy[i] * dt;
|
|
246
|
+
z[i] += vz[i] * dt;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Cache line padding to avoid false sharing
|
|
252
|
+
struct alignas(64) CacheLinePadded {
|
|
253
|
+
std::atomic<int> counter;
|
|
254
|
+
char padding[64 - sizeof(std::atomic<int>)];
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// Prefetching
|
|
258
|
+
void process_with_prefetch(const int* data, size_t size) {
|
|
259
|
+
for (size_t i = 0; i < size; ++i) {
|
|
260
|
+
// Prefetch data for next iteration
|
|
261
|
+
if (i + 8 < size) {
|
|
262
|
+
__builtin_prefetch(&data[i + 8], 0, 1);
|
|
263
|
+
}
|
|
264
|
+
// Process current data
|
|
265
|
+
process(data[i]);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
## Memory Pool
|
|
271
|
+
|
|
272
|
+
```cpp
|
|
273
|
+
#include <vector>
|
|
274
|
+
#include <memory>
|
|
275
|
+
|
|
276
|
+
template<typename T, size_t ChunkSize = 256>
|
|
277
|
+
class MemoryPool {
|
|
278
|
+
struct Chunk {
|
|
279
|
+
alignas(T) std::byte data[sizeof(T) * ChunkSize];
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
std::vector<std::unique_ptr<Chunk>> chunks_;
|
|
283
|
+
std::vector<T*> free_list_;
|
|
284
|
+
size_t current_chunk_offset_ = ChunkSize;
|
|
285
|
+
|
|
286
|
+
public:
|
|
287
|
+
T* allocate() {
|
|
288
|
+
if (!free_list_.empty()) {
|
|
289
|
+
T* ptr = free_list_.back();
|
|
290
|
+
free_list_.pop_back();
|
|
291
|
+
return ptr;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
if (current_chunk_offset_ >= ChunkSize) {
|
|
295
|
+
chunks_.push_back(std::make_unique<Chunk>());
|
|
296
|
+
current_chunk_offset_ = 0;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
Chunk* chunk = chunks_.back().get();
|
|
300
|
+
T* ptr = reinterpret_cast<T*>(
|
|
301
|
+
&chunk->data[sizeof(T) * current_chunk_offset_++]
|
|
302
|
+
);
|
|
303
|
+
return ptr;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
void deallocate(T* ptr) {
|
|
307
|
+
free_list_.push_back(ptr);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
template<typename... Args>
|
|
311
|
+
T* construct(Args&&... args) {
|
|
312
|
+
T* ptr = allocate();
|
|
313
|
+
new (ptr) T(std::forward<Args>(args)...);
|
|
314
|
+
return ptr;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
void destroy(T* ptr) {
|
|
318
|
+
ptr->~T();
|
|
319
|
+
deallocate(ptr);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
## Copy Elision and RVO
|
|
325
|
+
|
|
326
|
+
```cpp
|
|
327
|
+
// Return Value Optimization (RVO)
|
|
328
|
+
std::vector<int> create_vector() {
|
|
329
|
+
std::vector<int> vec{1, 2, 3, 4, 5};
|
|
330
|
+
return vec; // RVO applies, no copy/move
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Named Return Value Optimization (NRVO)
|
|
334
|
+
std::string build_string(bool condition) {
|
|
335
|
+
std::string result;
|
|
336
|
+
if (condition) {
|
|
337
|
+
result = "condition true";
|
|
338
|
+
} else {
|
|
339
|
+
result = "condition false";
|
|
340
|
+
}
|
|
341
|
+
return result; // NRVO may apply
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Guaranteed copy elision (C++17)
|
|
345
|
+
struct NonMovable {
|
|
346
|
+
NonMovable() = default;
|
|
347
|
+
NonMovable(const NonMovable&) = delete;
|
|
348
|
+
NonMovable(NonMovable&&) = delete;
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
NonMovable create() {
|
|
352
|
+
return NonMovable{}; // Guaranteed no copy/move in C++17
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
auto obj = create(); // OK in C++17
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Alignment and Memory Layout
|
|
359
|
+
|
|
360
|
+
```cpp
|
|
361
|
+
#include <cstddef>
|
|
362
|
+
|
|
363
|
+
// Control alignment
|
|
364
|
+
struct alignas(64) CacheAligned {
|
|
365
|
+
int data[16];
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
// Check alignment
|
|
369
|
+
static_assert(alignof(CacheAligned) == 64);
|
|
370
|
+
|
|
371
|
+
// Aligned allocation
|
|
372
|
+
void* aligned_alloc_wrapper(size_t alignment, size_t size) {
|
|
373
|
+
void* ptr = nullptr;
|
|
374
|
+
if (posix_memalign(&ptr, alignment, size) != 0) {
|
|
375
|
+
throw std::bad_alloc();
|
|
376
|
+
}
|
|
377
|
+
return ptr;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Placement new with alignment
|
|
381
|
+
alignas(32) std::byte buffer[sizeof(Data)];
|
|
382
|
+
Data* obj = new (buffer) Data();
|
|
383
|
+
obj->~Data(); // Manual destruction needed
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Quick Reference
|
|
387
|
+
|
|
388
|
+
| Technique | Use Case | Benefit |
|
|
389
|
+
|-----------|----------|---------|
|
|
390
|
+
| Smart Pointers | Ownership management | Memory safety |
|
|
391
|
+
| Move Semantics | Avoid copies | Performance |
|
|
392
|
+
| Custom Allocators | Specialized allocation | Speed + control |
|
|
393
|
+
| SIMD | Parallel computation | 4-8x speedup |
|
|
394
|
+
| SoA Layout | Sequential access | Cache efficiency |
|
|
395
|
+
| Memory Pools | Frequent alloc/dealloc | Reduced fragmentation |
|
|
396
|
+
| Alignment | SIMD/cache optimization | Performance |
|
|
397
|
+
| RVO/NRVO | Return objects | Zero-copy |
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
# Modern C++20/23 Features
|
|
2
|
+
|
|
3
|
+
## Concepts and Constraints
|
|
4
|
+
|
|
5
|
+
```cpp
|
|
6
|
+
#include <concepts>
|
|
7
|
+
|
|
8
|
+
// Define custom concepts
|
|
9
|
+
template<typename T>
|
|
10
|
+
concept Numeric = std::integral<T> || std::floating_point<T>;
|
|
11
|
+
|
|
12
|
+
template<typename T>
|
|
13
|
+
concept Hashable = requires(T a) {
|
|
14
|
+
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
template<typename T>
|
|
18
|
+
concept Container = requires(T c) {
|
|
19
|
+
typename T::value_type;
|
|
20
|
+
typename T::iterator;
|
|
21
|
+
{ c.begin() } -> std::same_as<typename T::iterator>;
|
|
22
|
+
{ c.end() } -> std::same_as<typename T::iterator>;
|
|
23
|
+
{ c.size() } -> std::convertible_to<std::size_t>;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
// Use concepts for function constraints
|
|
27
|
+
template<Numeric T>
|
|
28
|
+
T add(T a, T b) {
|
|
29
|
+
return a + b;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Concept-based overloading
|
|
33
|
+
template<std::integral T>
|
|
34
|
+
void process(T value) {
|
|
35
|
+
std::cout << "Processing integer: " << value << '\n';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
template<std::floating_point T>
|
|
39
|
+
void process(T value) {
|
|
40
|
+
std::cout << "Processing float: " << value << '\n';
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Ranges and Views
|
|
45
|
+
|
|
46
|
+
```cpp
|
|
47
|
+
#include <ranges>
|
|
48
|
+
#include <vector>
|
|
49
|
+
#include <algorithm>
|
|
50
|
+
|
|
51
|
+
// Ranges-based algorithms
|
|
52
|
+
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
|
53
|
+
|
|
54
|
+
// Filter, transform, take - all lazy evaluation
|
|
55
|
+
auto result = numbers
|
|
56
|
+
| std::views::filter([](int n) { return n % 2 == 0; })
|
|
57
|
+
| std::views::transform([](int n) { return n * n; })
|
|
58
|
+
| std::views::take(3);
|
|
59
|
+
|
|
60
|
+
// Copy to vector only when needed
|
|
61
|
+
std::vector<int> materialized(result.begin(), result.end());
|
|
62
|
+
|
|
63
|
+
// Custom range adaptor
|
|
64
|
+
auto is_even = [](int n) { return n % 2 == 0; };
|
|
65
|
+
auto square = [](int n) { return n * n; };
|
|
66
|
+
|
|
67
|
+
auto pipeline = std::views::filter(is_even)
|
|
68
|
+
| std::views::transform(square);
|
|
69
|
+
|
|
70
|
+
auto processed = numbers | pipeline;
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Coroutines
|
|
74
|
+
|
|
75
|
+
```cpp
|
|
76
|
+
#include <coroutine>
|
|
77
|
+
#include <iostream>
|
|
78
|
+
#include <memory>
|
|
79
|
+
|
|
80
|
+
// Generator coroutine
|
|
81
|
+
template<typename T>
|
|
82
|
+
struct Generator {
|
|
83
|
+
struct promise_type {
|
|
84
|
+
T current_value;
|
|
85
|
+
|
|
86
|
+
auto get_return_object() {
|
|
87
|
+
return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
std::suspend_always initial_suspend() { return {}; }
|
|
91
|
+
std::suspend_always final_suspend() noexcept { return {}; }
|
|
92
|
+
|
|
93
|
+
std::suspend_always yield_value(T value) {
|
|
94
|
+
current_value = value;
|
|
95
|
+
return {};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void return_void() {}
|
|
99
|
+
void unhandled_exception() { std::terminate(); }
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
std::coroutine_handle<promise_type> handle;
|
|
103
|
+
|
|
104
|
+
Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
|
|
105
|
+
~Generator() { if (handle) handle.destroy(); }
|
|
106
|
+
|
|
107
|
+
bool move_next() {
|
|
108
|
+
handle.resume();
|
|
109
|
+
return !handle.done();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
T current_value() {
|
|
113
|
+
return handle.promise().current_value;
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Usage
|
|
118
|
+
Generator<int> fibonacci() {
|
|
119
|
+
int a = 0, b = 1;
|
|
120
|
+
while (true) {
|
|
121
|
+
co_yield a;
|
|
122
|
+
auto next = a + b;
|
|
123
|
+
a = b;
|
|
124
|
+
b = next;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Async coroutine
|
|
129
|
+
#include <future>
|
|
130
|
+
|
|
131
|
+
struct Task {
|
|
132
|
+
struct promise_type {
|
|
133
|
+
Task get_return_object() {
|
|
134
|
+
return Task{std::coroutine_handle<promise_type>::from_promise(*this)};
|
|
135
|
+
}
|
|
136
|
+
std::suspend_never initial_suspend() { return {}; }
|
|
137
|
+
std::suspend_never final_suspend() noexcept { return {}; }
|
|
138
|
+
void return_void() {}
|
|
139
|
+
void unhandled_exception() {}
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
std::coroutine_handle<promise_type> handle;
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
Task async_operation() {
|
|
146
|
+
std::cout << "Starting async work\n";
|
|
147
|
+
co_await std::suspend_always{};
|
|
148
|
+
std::cout << "Resuming async work\n";
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Three-Way Comparison (Spaceship)
|
|
153
|
+
|
|
154
|
+
```cpp
|
|
155
|
+
#include <compare>
|
|
156
|
+
|
|
157
|
+
struct Point {
|
|
158
|
+
int x, y;
|
|
159
|
+
|
|
160
|
+
// Auto-generate all comparison operators
|
|
161
|
+
auto operator<=>(const Point&) const = default;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Custom spaceship operator
|
|
165
|
+
struct Version {
|
|
166
|
+
int major, minor, patch;
|
|
167
|
+
|
|
168
|
+
std::strong_ordering operator<=>(const Version& other) const {
|
|
169
|
+
if (auto cmp = major <=> other.major; cmp != 0) return cmp;
|
|
170
|
+
if (auto cmp = minor <=> other.minor; cmp != 0) return cmp;
|
|
171
|
+
return patch <=> other.patch;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
bool operator==(const Version& other) const = default;
|
|
175
|
+
};
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Designated Initializers
|
|
179
|
+
|
|
180
|
+
```cpp
|
|
181
|
+
struct Config {
|
|
182
|
+
std::string host = "localhost";
|
|
183
|
+
int port = 8080;
|
|
184
|
+
bool ssl_enabled = false;
|
|
185
|
+
int timeout_ms = 5000;
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
// C++20 designated initializers
|
|
189
|
+
Config cfg {
|
|
190
|
+
.host = "example.com",
|
|
191
|
+
.port = 443,
|
|
192
|
+
.ssl_enabled = true
|
|
193
|
+
// timeout_ms uses default
|
|
194
|
+
};
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
## Modules (C++20)
|
|
198
|
+
|
|
199
|
+
```cpp
|
|
200
|
+
// math.cppm - module interface
|
|
201
|
+
export module math;
|
|
202
|
+
|
|
203
|
+
export namespace math {
|
|
204
|
+
template<typename T>
|
|
205
|
+
T add(T a, T b) {
|
|
206
|
+
return a + b;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
class Calculator {
|
|
210
|
+
public:
|
|
211
|
+
int multiply(int a, int b);
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Implementation
|
|
216
|
+
module math;
|
|
217
|
+
|
|
218
|
+
int math::Calculator::multiply(int a, int b) {
|
|
219
|
+
return a * b;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Usage in other files
|
|
223
|
+
import math;
|
|
224
|
+
|
|
225
|
+
int main() {
|
|
226
|
+
auto result = math::add(5, 3);
|
|
227
|
+
math::Calculator calc;
|
|
228
|
+
auto product = calc.multiply(4, 7);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## constexpr Enhancements
|
|
233
|
+
|
|
234
|
+
```cpp
|
|
235
|
+
#include <string>
|
|
236
|
+
#include <vector>
|
|
237
|
+
#include <algorithm>
|
|
238
|
+
|
|
239
|
+
// C++20: constexpr std::string and std::vector
|
|
240
|
+
constexpr auto compute_at_compile_time() {
|
|
241
|
+
std::vector<int> vec{1, 2, 3, 4, 5};
|
|
242
|
+
std::ranges::reverse(vec);
|
|
243
|
+
return vec[0]; // Returns 5
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
constexpr int value = compute_at_compile_time();
|
|
247
|
+
|
|
248
|
+
// constexpr virtual functions (C++20)
|
|
249
|
+
struct Base {
|
|
250
|
+
constexpr virtual int get_value() const { return 42; }
|
|
251
|
+
constexpr virtual ~Base() = default;
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
struct Derived : Base {
|
|
255
|
+
constexpr int get_value() const override { return 100; }
|
|
256
|
+
};
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## std::format (C++20)
|
|
260
|
+
|
|
261
|
+
```cpp
|
|
262
|
+
#include <format>
|
|
263
|
+
#include <iostream>
|
|
264
|
+
|
|
265
|
+
int main() {
|
|
266
|
+
std::string msg = std::format("Hello, {}!", "World");
|
|
267
|
+
|
|
268
|
+
// Positional arguments
|
|
269
|
+
auto text = std::format("{1} {0}", "World", "Hello");
|
|
270
|
+
|
|
271
|
+
// Formatting options
|
|
272
|
+
double pi = 3.14159265;
|
|
273
|
+
auto formatted = std::format("Pi: {:.2f}", pi); // "Pi: 3.14"
|
|
274
|
+
|
|
275
|
+
// Custom types
|
|
276
|
+
struct Point { int x, y; };
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Custom formatter
|
|
280
|
+
template<>
|
|
281
|
+
struct std::formatter<Point> {
|
|
282
|
+
constexpr auto parse(format_parse_context& ctx) {
|
|
283
|
+
return ctx.begin();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
auto format(const Point& p, format_context& ctx) const {
|
|
287
|
+
return std::format_to(ctx.out(), "({}, {})", p.x, p.y);
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
## Quick Reference
|
|
293
|
+
|
|
294
|
+
| Feature | C++17 | C++20 | C++23 |
|
|
295
|
+
|---------|-------|-------|-------|
|
|
296
|
+
| Concepts | - | ✓ | ✓ |
|
|
297
|
+
| Ranges | - | ✓ | ✓ |
|
|
298
|
+
| Coroutines | - | ✓ | ✓ |
|
|
299
|
+
| Modules | - | ✓ | ✓ |
|
|
300
|
+
| Spaceship | - | ✓ | ✓ |
|
|
301
|
+
| std::format | - | ✓ | ✓ |
|
|
302
|
+
| std::expected | - | - | ✓ |
|
|
303
|
+
| std::print | - | - | ✓ |
|
|
304
|
+
| Deducing this | - | - | ✓ |
|