agentic-team-templates 0.13.1 → 0.14.0
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/README.md +6 -1
- package/package.json +1 -1
- package/src/index.js +22 -2
- package/src/index.test.js +5 -0
- package/templates/cpp-expert/.cursorrules/concurrency.md +211 -0
- package/templates/cpp-expert/.cursorrules/error-handling.md +170 -0
- package/templates/cpp-expert/.cursorrules/memory-and-ownership.md +220 -0
- package/templates/cpp-expert/.cursorrules/modern-cpp.md +211 -0
- package/templates/cpp-expert/.cursorrules/overview.md +87 -0
- package/templates/cpp-expert/.cursorrules/performance.md +223 -0
- package/templates/cpp-expert/.cursorrules/testing.md +230 -0
- package/templates/cpp-expert/.cursorrules/tooling.md +312 -0
- package/templates/cpp-expert/CLAUDE.md +242 -0
- package/templates/csharp-expert/.cursorrules/aspnet-core.md +311 -0
- package/templates/csharp-expert/.cursorrules/async-patterns.md +206 -0
- package/templates/csharp-expert/.cursorrules/dependency-injection.md +206 -0
- package/templates/csharp-expert/.cursorrules/error-handling.md +235 -0
- package/templates/csharp-expert/.cursorrules/language-features.md +204 -0
- package/templates/csharp-expert/.cursorrules/overview.md +92 -0
- package/templates/csharp-expert/.cursorrules/performance.md +251 -0
- package/templates/csharp-expert/.cursorrules/testing.md +282 -0
- package/templates/csharp-expert/.cursorrules/tooling.md +254 -0
- package/templates/csharp-expert/CLAUDE.md +360 -0
- package/templates/java-expert/.cursorrules/concurrency.md +209 -0
- package/templates/java-expert/.cursorrules/error-handling.md +205 -0
- package/templates/java-expert/.cursorrules/modern-java.md +216 -0
- package/templates/java-expert/.cursorrules/overview.md +81 -0
- package/templates/java-expert/.cursorrules/performance.md +239 -0
- package/templates/java-expert/.cursorrules/persistence.md +262 -0
- package/templates/java-expert/.cursorrules/spring-boot.md +262 -0
- package/templates/java-expert/.cursorrules/testing.md +272 -0
- package/templates/java-expert/.cursorrules/tooling.md +301 -0
- package/templates/java-expert/CLAUDE.md +325 -0
- package/templates/javascript-expert/.cursorrules/overview.md +5 -3
- package/templates/javascript-expert/.cursorrules/typescript-deep-dive.md +348 -0
- package/templates/javascript-expert/CLAUDE.md +34 -3
- package/templates/kotlin-expert/.cursorrules/coroutines.md +237 -0
- package/templates/kotlin-expert/.cursorrules/error-handling.md +149 -0
- package/templates/kotlin-expert/.cursorrules/frameworks.md +227 -0
- package/templates/kotlin-expert/.cursorrules/language-features.md +231 -0
- package/templates/kotlin-expert/.cursorrules/overview.md +77 -0
- package/templates/kotlin-expert/.cursorrules/performance.md +185 -0
- package/templates/kotlin-expert/.cursorrules/testing.md +213 -0
- package/templates/kotlin-expert/.cursorrules/tooling.md +258 -0
- package/templates/kotlin-expert/CLAUDE.md +276 -0
- package/templates/swift-expert/.cursorrules/concurrency.md +230 -0
- package/templates/swift-expert/.cursorrules/error-handling.md +213 -0
- package/templates/swift-expert/.cursorrules/language-features.md +246 -0
- package/templates/swift-expert/.cursorrules/overview.md +88 -0
- package/templates/swift-expert/.cursorrules/performance.md +260 -0
- package/templates/swift-expert/.cursorrules/swiftui.md +260 -0
- package/templates/swift-expert/.cursorrules/testing.md +286 -0
- package/templates/swift-expert/.cursorrules/tooling.md +285 -0
- package/templates/swift-expert/CLAUDE.md +275 -0
package/README.md
CHANGED
|
@@ -148,13 +148,17 @@ npx agentic-team-templates --reset --force
|
|
|
148
148
|
| Template | Description |
|
|
149
149
|
|----------|-------------|
|
|
150
150
|
| `blockchain` | Smart contracts, DeFi protocols, and Web3 applications (Solidity, Foundry, Viem) |
|
|
151
|
+
| `cpp-expert` | Principal-level C++ engineering (modern C++, RAII, concurrency, templates, performance) |
|
|
152
|
+
| `csharp-expert` | Principal-level C# engineering (async, DI, EF Core, ASP.NET Core, testing) |
|
|
151
153
|
| `cli-tools` | Command-line applications and developer tools (Cobra, Commander, Click) |
|
|
152
154
|
| `data-engineering` | Data platforms and pipelines (ETL, data modeling, data quality) |
|
|
153
155
|
| `devops-sre` | DevOps and SRE practices (incident management, observability, SLOs, chaos engineering) |
|
|
154
156
|
| `documentation` | Technical documentation standards (READMEs, API docs, ADRs, code comments) |
|
|
155
157
|
| `fullstack` | Full-stack web applications (Next.js, Nuxt, SvelteKit, Remix) |
|
|
156
158
|
| `golang-expert` | Principal-level Go engineering (concurrency, stdlib, production patterns, testing) |
|
|
157
|
-
| `
|
|
159
|
+
| `kotlin-expert` | Principal-level Kotlin engineering (coroutines, multiplatform, Ktor, Spring Boot, testing) |
|
|
160
|
+
| `javascript-expert` | Principal-level JavaScript & TypeScript engineering (Node.js, React, type system, testing) |
|
|
161
|
+
| `java-expert` | Principal-level Java engineering (JVM, Spring Boot, concurrency, JPA, testing) |
|
|
158
162
|
| `ml-ai` | Machine learning and AI systems (model development, deployment, monitoring) |
|
|
159
163
|
| `mobile` | Mobile applications (React Native, Flutter, native iOS/Android) |
|
|
160
164
|
| `platform-engineering` | Internal developer platforms, infrastructure automation, reliability engineering |
|
|
@@ -162,6 +166,7 @@ npx agentic-team-templates --reset --force
|
|
|
162
166
|
| `python-expert` | Principal-level Python engineering (type system, async, testing, FastAPI, Django) |
|
|
163
167
|
| `qa-engineering` | Quality assurance programs for confident, rapid software delivery |
|
|
164
168
|
| `rust-expert` | Principal-level Rust engineering (ownership, concurrency, unsafe, traits, async) |
|
|
169
|
+
| `swift-expert` | Principal-level Swift engineering (concurrency, SwiftUI, protocols, testing, Apple platforms) |
|
|
165
170
|
| `testing` | Comprehensive testing practices (TDD, test design, CI/CD integration, performance testing) |
|
|
166
171
|
| `utility-agent` | AI agent utilities with context management and hallucination prevention |
|
|
167
172
|
| `web-backend` | Backend APIs and services (REST, GraphQL, microservices) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-team-templates",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "AI coding assistant templates for Cursor IDE. Pre-configured rules and guidelines that help AI assistants write better code. - use at your own risk",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cursor",
|
package/src/index.js
CHANGED
|
@@ -24,6 +24,14 @@ const TEMPLATES = {
|
|
|
24
24
|
description: 'Smart contracts, DeFi protocols, and Web3 applications (Solidity, Foundry, Viem)',
|
|
25
25
|
rules: ['defi-patterns.md', 'gas-optimization.md', 'overview.md', 'security.md', 'smart-contracts.md', 'testing.md', 'web3-integration.md']
|
|
26
26
|
},
|
|
27
|
+
'cpp-expert': {
|
|
28
|
+
description: 'Principal-level C++ engineering (modern C++, RAII, concurrency, templates, performance)',
|
|
29
|
+
rules: ['concurrency.md', 'error-handling.md', 'memory-and-ownership.md', 'modern-cpp.md', 'overview.md', 'performance.md', 'testing.md', 'tooling.md']
|
|
30
|
+
},
|
|
31
|
+
'csharp-expert': {
|
|
32
|
+
description: 'Principal-level C# engineering (async, DI, EF Core, ASP.NET Core, testing)',
|
|
33
|
+
rules: ['aspnet-core.md', 'async-patterns.md', 'dependency-injection.md', 'error-handling.md', 'language-features.md', 'overview.md', 'performance.md', 'testing.md', 'tooling.md']
|
|
34
|
+
},
|
|
27
35
|
'cli-tools': {
|
|
28
36
|
description: 'Command-line applications and developer tools (Cobra, Commander, Click)',
|
|
29
37
|
rules: ['architecture.md', 'arguments.md', 'distribution.md', 'error-handling.md', 'overview.md', 'testing.md', 'user-experience.md']
|
|
@@ -48,9 +56,17 @@ const TEMPLATES = {
|
|
|
48
56
|
description: 'Principal-level Go engineering (concurrency, stdlib, production patterns, testing)',
|
|
49
57
|
rules: ['concurrency.md', 'error-handling.md', 'interfaces-and-types.md', 'overview.md', 'performance.md', 'production-patterns.md', 'stdlib-and-tooling.md', 'testing.md']
|
|
50
58
|
},
|
|
59
|
+
'java-expert': {
|
|
60
|
+
description: 'Principal-level Java engineering (JVM, Spring Boot, concurrency, JPA, testing)',
|
|
61
|
+
rules: ['concurrency.md', 'error-handling.md', 'modern-java.md', 'overview.md', 'performance.md', 'persistence.md', 'spring-boot.md', 'testing.md', 'tooling.md']
|
|
62
|
+
},
|
|
51
63
|
'javascript-expert': {
|
|
52
|
-
description: 'Principal-level JavaScript engineering
|
|
53
|
-
rules: ['language-deep-dive.md', 'node-patterns.md', 'overview.md', 'performance.md', 'react-patterns.md', 'testing.md', 'tooling.md']
|
|
64
|
+
description: 'Principal-level JavaScript & TypeScript engineering (Node.js, React, type system, testing)',
|
|
65
|
+
rules: ['language-deep-dive.md', 'node-patterns.md', 'overview.md', 'performance.md', 'react-patterns.md', 'testing.md', 'tooling.md', 'typescript-deep-dive.md']
|
|
66
|
+
},
|
|
67
|
+
'kotlin-expert': {
|
|
68
|
+
description: 'Principal-level Kotlin engineering (coroutines, multiplatform, Ktor, Spring Boot, testing)',
|
|
69
|
+
rules: ['coroutines.md', 'error-handling.md', 'frameworks.md', 'language-features.md', 'overview.md', 'performance.md', 'testing.md', 'tooling.md']
|
|
54
70
|
},
|
|
55
71
|
'ml-ai': {
|
|
56
72
|
description: 'Machine learning and AI systems (model development, deployment, monitoring)',
|
|
@@ -80,6 +96,10 @@ const TEMPLATES = {
|
|
|
80
96
|
description: 'Principal-level Rust engineering (ownership, concurrency, unsafe, traits, async)',
|
|
81
97
|
rules: ['concurrency.md', 'ecosystem-and-tooling.md', 'error-handling.md', 'overview.md', 'ownership-and-borrowing.md', 'performance-and-unsafe.md', 'testing.md', 'traits-and-generics.md']
|
|
82
98
|
},
|
|
99
|
+
'swift-expert': {
|
|
100
|
+
description: 'Principal-level Swift engineering (concurrency, SwiftUI, protocols, testing, Apple platforms)',
|
|
101
|
+
rules: ['concurrency.md', 'error-handling.md', 'language-features.md', 'overview.md', 'performance.md', 'swiftui.md', 'testing.md', 'tooling.md']
|
|
102
|
+
},
|
|
83
103
|
'testing': {
|
|
84
104
|
description: 'Comprehensive testing practices (TDD, test design, CI/CD integration, performance testing)',
|
|
85
105
|
rules: ['advanced-techniques.md', 'ci-cd-integration.md', 'overview.md', 'performance-testing.md', 'quality-metrics.md', 'reliability.md', 'tdd-methodology.md', 'test-data.md', 'test-design.md', 'test-types.md']
|
package/src/index.test.js
CHANGED
|
@@ -74,13 +74,17 @@ describe('Constants', () => {
|
|
|
74
74
|
it('should have all expected templates', () => {
|
|
75
75
|
const expectedTemplates = [
|
|
76
76
|
'blockchain',
|
|
77
|
+
'cpp-expert',
|
|
78
|
+
'csharp-expert',
|
|
77
79
|
'cli-tools',
|
|
78
80
|
'data-engineering',
|
|
79
81
|
'devops-sre',
|
|
80
82
|
'documentation',
|
|
81
83
|
'fullstack',
|
|
82
84
|
'golang-expert',
|
|
85
|
+
'java-expert',
|
|
83
86
|
'javascript-expert',
|
|
87
|
+
'kotlin-expert',
|
|
84
88
|
'ml-ai',
|
|
85
89
|
'mobile',
|
|
86
90
|
'platform-engineering',
|
|
@@ -88,6 +92,7 @@ describe('Constants', () => {
|
|
|
88
92
|
'python-expert',
|
|
89
93
|
'qa-engineering',
|
|
90
94
|
'rust-expert',
|
|
95
|
+
'swift-expert',
|
|
91
96
|
'testing',
|
|
92
97
|
'utility-agent',
|
|
93
98
|
'web-backend',
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# C++ Concurrency
|
|
2
|
+
|
|
3
|
+
The C++ memory model is the law. Every concurrent access must be explicitly synchronized.
|
|
4
|
+
|
|
5
|
+
## std::thread and std::jthread
|
|
6
|
+
|
|
7
|
+
```cpp
|
|
8
|
+
// std::jthread (C++20) — automatically joins on destruction
|
|
9
|
+
void process_data(std::stop_token stop, std::span<const Item> items) {
|
|
10
|
+
for (const auto& item : items) {
|
|
11
|
+
if (stop.stop_requested()) return;
|
|
12
|
+
process(item);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
auto worker = std::jthread(process_data, data);
|
|
17
|
+
// Automatically joins when worker goes out of scope
|
|
18
|
+
// Can request stop: worker.request_stop();
|
|
19
|
+
|
|
20
|
+
// Never use std::thread without join/detach — it calls std::terminate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Mutex and Locking
|
|
24
|
+
|
|
25
|
+
```cpp
|
|
26
|
+
// RAII locking — always
|
|
27
|
+
class ThreadSafeCounter {
|
|
28
|
+
mutable std::mutex mutex_;
|
|
29
|
+
int count_ = 0;
|
|
30
|
+
|
|
31
|
+
public:
|
|
32
|
+
void increment() {
|
|
33
|
+
std::lock_guard lock(mutex_);
|
|
34
|
+
++count_;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
int get() const {
|
|
38
|
+
std::lock_guard lock(mutex_);
|
|
39
|
+
return count_;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// Multiple mutexes — use std::scoped_lock to avoid deadlock
|
|
44
|
+
void transfer(Account& from, Account& to, int amount) {
|
|
45
|
+
std::scoped_lock lock(from.mutex_, to.mutex_); // Deadlock-free
|
|
46
|
+
from.balance_ -= amount;
|
|
47
|
+
to.balance_ += amount;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Read-heavy workloads — use shared_mutex
|
|
51
|
+
class Cache {
|
|
52
|
+
mutable std::shared_mutex mutex_;
|
|
53
|
+
std::unordered_map<std::string, Value> data_;
|
|
54
|
+
|
|
55
|
+
public:
|
|
56
|
+
auto get(const std::string& key) const -> std::optional<Value> {
|
|
57
|
+
std::shared_lock lock(mutex_); // Multiple readers OK
|
|
58
|
+
auto it = data_.find(key);
|
|
59
|
+
return it != data_.end() ? std::optional{it->second} : std::nullopt;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
void set(const std::string& key, Value value) {
|
|
63
|
+
std::unique_lock lock(mutex_); // Exclusive write
|
|
64
|
+
data_[key] = std::move(value);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Atomics
|
|
70
|
+
|
|
71
|
+
```cpp
|
|
72
|
+
// Lock-free operations for simple types
|
|
73
|
+
std::atomic<int> counter{0};
|
|
74
|
+
counter.fetch_add(1, std::memory_order_relaxed); // Fastest for counters
|
|
75
|
+
|
|
76
|
+
// Flags
|
|
77
|
+
std::atomic<bool> ready{false};
|
|
78
|
+
// Producer:
|
|
79
|
+
data = prepare();
|
|
80
|
+
ready.store(true, std::memory_order_release);
|
|
81
|
+
// Consumer:
|
|
82
|
+
while (!ready.load(std::memory_order_acquire)) { /* spin or yield */ }
|
|
83
|
+
use(data); // Guaranteed to see prepared data
|
|
84
|
+
|
|
85
|
+
// std::atomic_ref (C++20) for non-atomic variables
|
|
86
|
+
int value = 0;
|
|
87
|
+
std::atomic_ref ref{value};
|
|
88
|
+
ref.fetch_add(1);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Condition Variables
|
|
92
|
+
|
|
93
|
+
```cpp
|
|
94
|
+
template <typename T>
|
|
95
|
+
class BoundedQueue {
|
|
96
|
+
std::queue<T> queue_;
|
|
97
|
+
mutable std::mutex mutex_;
|
|
98
|
+
std::condition_variable not_empty_;
|
|
99
|
+
std::condition_variable not_full_;
|
|
100
|
+
size_t max_size_;
|
|
101
|
+
|
|
102
|
+
public:
|
|
103
|
+
explicit BoundedQueue(size_t max_size) : max_size_{max_size} {}
|
|
104
|
+
|
|
105
|
+
void push(T item) {
|
|
106
|
+
std::unique_lock lock(mutex_);
|
|
107
|
+
not_full_.wait(lock, [this] { return queue_.size() < max_size_; });
|
|
108
|
+
queue_.push(std::move(item));
|
|
109
|
+
not_empty_.notify_one();
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
auto pop() -> T {
|
|
113
|
+
std::unique_lock lock(mutex_);
|
|
114
|
+
not_empty_.wait(lock, [this] { return !queue_.empty(); });
|
|
115
|
+
auto item = std::move(queue_.front());
|
|
116
|
+
queue_.pop();
|
|
117
|
+
not_full_.notify_one();
|
|
118
|
+
return item;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
auto try_pop(std::chrono::milliseconds timeout) -> std::optional<T> {
|
|
122
|
+
std::unique_lock lock(mutex_);
|
|
123
|
+
if (!not_empty_.wait_for(lock, timeout, [this] { return !queue_.empty(); })) {
|
|
124
|
+
return std::nullopt;
|
|
125
|
+
}
|
|
126
|
+
auto item = std::move(queue_.front());
|
|
127
|
+
queue_.pop();
|
|
128
|
+
not_full_.notify_one();
|
|
129
|
+
return item;
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Async and Futures
|
|
135
|
+
|
|
136
|
+
```cpp
|
|
137
|
+
// std::async for fire-and-forget parallel work
|
|
138
|
+
auto future = std::async(std::launch::async, [] {
|
|
139
|
+
return expensive_computation();
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
auto result = future.get(); // Blocks until ready
|
|
143
|
+
|
|
144
|
+
// Parallel independent work
|
|
145
|
+
auto user_future = std::async(std::launch::async, [&] { return fetch_user(id); });
|
|
146
|
+
auto orders_future = std::async(std::launch::async, [&] { return fetch_orders(id); });
|
|
147
|
+
|
|
148
|
+
auto user = user_future.get();
|
|
149
|
+
auto orders = orders_future.get();
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Parallel Algorithms (C++17)
|
|
153
|
+
|
|
154
|
+
```cpp
|
|
155
|
+
#include <execution>
|
|
156
|
+
|
|
157
|
+
// Parallel sort
|
|
158
|
+
std::sort(std::execution::par, data.begin(), data.end());
|
|
159
|
+
|
|
160
|
+
// Parallel transform-reduce
|
|
161
|
+
auto total = std::transform_reduce(
|
|
162
|
+
std::execution::par,
|
|
163
|
+
orders.begin(), orders.end(),
|
|
164
|
+
0.0, // Initial value
|
|
165
|
+
std::plus<>{}, // Reduce
|
|
166
|
+
[](const Order& o) { return o.total(); } // Transform
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
// Parallel for_each
|
|
170
|
+
std::for_each(std::execution::par_unseq, items.begin(), items.end(),
|
|
171
|
+
[](auto& item) { item.process(); });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Thread Safety Rules
|
|
175
|
+
|
|
176
|
+
1. **Immutable data is thread-safe** — share freely via `const` references
|
|
177
|
+
2. **Every mutable shared state needs synchronization** — no exceptions
|
|
178
|
+
3. **Prefer lock-free data structures** when correctness is provable
|
|
179
|
+
4. **Hold locks for the minimum time** — compute outside the critical section
|
|
180
|
+
5. **Never hold two locks simultaneously** unless using `std::scoped_lock`
|
|
181
|
+
6. **Use `std::atomic` for single variables**, mutex for compound operations
|
|
182
|
+
|
|
183
|
+
## Anti-Patterns
|
|
184
|
+
|
|
185
|
+
```cpp
|
|
186
|
+
// Never: lock and forget
|
|
187
|
+
mutex_.lock();
|
|
188
|
+
do_work(); // If this throws, mutex stays locked forever
|
|
189
|
+
mutex_.unlock();
|
|
190
|
+
// Use: std::lock_guard or std::unique_lock (RAII)
|
|
191
|
+
|
|
192
|
+
// Never: double-checked locking without atomics
|
|
193
|
+
if (!instance) {
|
|
194
|
+
std::lock_guard lock(mutex);
|
|
195
|
+
if (!instance) instance = new Singleton(); // Data race!
|
|
196
|
+
}
|
|
197
|
+
// Use: std::call_once or static local (Meyers singleton)
|
|
198
|
+
|
|
199
|
+
static Singleton& instance() {
|
|
200
|
+
static Singleton s; // Thread-safe in C++11+
|
|
201
|
+
return s;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Never: volatile for synchronization
|
|
205
|
+
volatile int flag; // volatile != atomic in C++
|
|
206
|
+
// Use: std::atomic<int> flag;
|
|
207
|
+
|
|
208
|
+
// Never: busy-waiting without yield
|
|
209
|
+
while (!ready.load()) {} // Burns CPU
|
|
210
|
+
// Use: condition_variable, or at least std::this_thread::yield()
|
|
211
|
+
```
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# C++ Error Handling
|
|
2
|
+
|
|
3
|
+
Exceptions for exceptional conditions. Error codes and std::expected for expected failures. RAII guarantees cleanup.
|
|
4
|
+
|
|
5
|
+
## Exception Safety Guarantees
|
|
6
|
+
|
|
7
|
+
Every function provides one of these guarantees — document which:
|
|
8
|
+
|
|
9
|
+
1. **No-throw** — Function never throws. Mark `noexcept`. (Destructors, move operations, swap)
|
|
10
|
+
2. **Strong** — If exception thrown, state rolls back to before the call. (Transaction semantics)
|
|
11
|
+
3. **Basic** — If exception thrown, invariants preserved, no leaks. (The minimum acceptable guarantee)
|
|
12
|
+
4. **No guarantee** — Avoid. This is a bug.
|
|
13
|
+
|
|
14
|
+
```cpp
|
|
15
|
+
// No-throw: destructors, move constructors, swap
|
|
16
|
+
Buffer(Buffer&& other) noexcept;
|
|
17
|
+
~Buffer() noexcept; // Implicit, but be explicit
|
|
18
|
+
|
|
19
|
+
// Strong: copy-and-swap idiom
|
|
20
|
+
auto operator=(Buffer other) -> Buffer& { // Takes by value (copies)
|
|
21
|
+
swap(*this, other); // noexcept swap
|
|
22
|
+
return *this; // Old data destroyed in 'other'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Basic: RAII handles cleanup even if later operations throw
|
|
26
|
+
void process(const std::string& path) {
|
|
27
|
+
auto file = open_file(path); // RAII — cleaned up if next line throws
|
|
28
|
+
auto data = parse(file); // RAII — cleaned up if next line throws
|
|
29
|
+
validate(data); // If this throws, file and data cleaned up
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Exceptions
|
|
34
|
+
|
|
35
|
+
```cpp
|
|
36
|
+
// Throw by value, catch by const reference
|
|
37
|
+
class ApplicationError : public std::runtime_error {
|
|
38
|
+
std::string code_;
|
|
39
|
+
public:
|
|
40
|
+
ApplicationError(std::string code, const std::string& message)
|
|
41
|
+
: std::runtime_error(message), code_{std::move(code)} {}
|
|
42
|
+
|
|
43
|
+
const std::string& code() const noexcept { return code_; }
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
class NotFoundError : public ApplicationError {
|
|
47
|
+
public:
|
|
48
|
+
NotFoundError(const std::string& entity, const std::string& id)
|
|
49
|
+
: ApplicationError("NOT_FOUND",
|
|
50
|
+
fmt::format("{} '{}' not found", entity, id)) {}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Catch specific exceptions first
|
|
54
|
+
try {
|
|
55
|
+
auto user = find_user(id);
|
|
56
|
+
} catch (const NotFoundError& e) {
|
|
57
|
+
return http::response(404, e.what());
|
|
58
|
+
} catch (const ApplicationError& e) {
|
|
59
|
+
return http::response(400, e.what());
|
|
60
|
+
} catch (const std::exception& e) {
|
|
61
|
+
log::error("Unexpected error: {}", e.what());
|
|
62
|
+
return http::response(500, "Internal error");
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## std::expected (C++23)
|
|
67
|
+
|
|
68
|
+
```cpp
|
|
69
|
+
// For expected failures — no exception overhead
|
|
70
|
+
enum class ValidationError { empty_name, invalid_email, duplicate_email };
|
|
71
|
+
|
|
72
|
+
auto validate_user(const CreateUserRequest& req)
|
|
73
|
+
-> std::expected<ValidatedUser, ValidationError>
|
|
74
|
+
{
|
|
75
|
+
if (req.name.empty())
|
|
76
|
+
return std::unexpected{ValidationError::empty_name};
|
|
77
|
+
if (!is_valid_email(req.email))
|
|
78
|
+
return std::unexpected{ValidationError::invalid_email};
|
|
79
|
+
return ValidatedUser{req.name, req.email};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Monadic chaining
|
|
83
|
+
auto result = validate_user(request)
|
|
84
|
+
.and_then([&](auto user) { return save_user(db, user); })
|
|
85
|
+
.transform([](auto saved) { return UserResponse::from(saved); });
|
|
86
|
+
|
|
87
|
+
if (!result) {
|
|
88
|
+
handle_error(result.error());
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Error Codes (C-style APIs)
|
|
93
|
+
|
|
94
|
+
```cpp
|
|
95
|
+
// std::error_code / std::error_condition for system-level errors
|
|
96
|
+
auto read_file(const std::filesystem::path& path)
|
|
97
|
+
-> std::expected<std::string, std::error_code>
|
|
98
|
+
{
|
|
99
|
+
std::error_code ec;
|
|
100
|
+
auto size = std::filesystem::file_size(path, ec);
|
|
101
|
+
if (ec) return std::unexpected{ec};
|
|
102
|
+
|
|
103
|
+
std::ifstream file(path);
|
|
104
|
+
if (!file) return std::unexpected{
|
|
105
|
+
std::make_error_code(std::errc::io_error)};
|
|
106
|
+
|
|
107
|
+
std::string content(size, '\0');
|
|
108
|
+
file.read(content.data(), static_cast<std::streamsize>(size));
|
|
109
|
+
return content;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## noexcept
|
|
114
|
+
|
|
115
|
+
```cpp
|
|
116
|
+
// Mark functions noexcept when they genuinely cannot throw
|
|
117
|
+
// The compiler can optimize based on this — and std::terminate if violated
|
|
118
|
+
|
|
119
|
+
// Always noexcept:
|
|
120
|
+
~MyClass() noexcept; // Destructors (implicit)
|
|
121
|
+
MyClass(MyClass&& other) noexcept; // Move constructor
|
|
122
|
+
MyClass& operator=(MyClass&& other) noexcept; // Move assignment
|
|
123
|
+
friend void swap(MyClass& a, MyClass& b) noexcept;
|
|
124
|
+
|
|
125
|
+
// Conditional noexcept:
|
|
126
|
+
template <typename T>
|
|
127
|
+
void process(T&& value) noexcept(noexcept(value.do_work())) {
|
|
128
|
+
value.do_work();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Why it matters: containers like std::vector will COPY instead of MOVE
|
|
132
|
+
// if move constructor is not noexcept (strong exception guarantee)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Assertions and Contracts
|
|
136
|
+
|
|
137
|
+
```cpp
|
|
138
|
+
// Debug-only checks for programmer errors (not user input)
|
|
139
|
+
#include <cassert>
|
|
140
|
+
|
|
141
|
+
void process(std::span<const int> data) {
|
|
142
|
+
assert(!data.empty() && "process() called with empty data");
|
|
143
|
+
// assert is removed in release builds
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Static assertions for compile-time invariants
|
|
147
|
+
static_assert(sizeof(Packet) == 64, "Packet must be exactly 64 bytes for alignment");
|
|
148
|
+
static_assert(std::is_nothrow_move_constructible_v<Buffer>,
|
|
149
|
+
"Buffer must be nothrow-movable for vector reallocation");
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Anti-Patterns
|
|
153
|
+
|
|
154
|
+
```cpp
|
|
155
|
+
// Never: catch(...) without rethrowing
|
|
156
|
+
try { do_work(); }
|
|
157
|
+
catch (...) { /* swallowed */ }
|
|
158
|
+
// At minimum: catch (...) { log_error(); throw; }
|
|
159
|
+
|
|
160
|
+
// Never: throwing in destructors
|
|
161
|
+
~MyClass() { throw std::runtime_error("cleanup failed"); }
|
|
162
|
+
// std::terminate will be called. Log and continue.
|
|
163
|
+
|
|
164
|
+
// Never: exceptions across DLL/shared library boundaries (ABI mismatch)
|
|
165
|
+
// Use error codes or std::expected at library boundaries
|
|
166
|
+
|
|
167
|
+
// Never: using exception specifications (deprecated)
|
|
168
|
+
void func() throw(std::exception); // Deprecated and removed in C++17
|
|
169
|
+
// Use: noexcept or nothing
|
|
170
|
+
```
|