agentic-team-templates 0.13.2 → 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
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Memory and Ownership
|
|
2
|
+
|
|
3
|
+
RAII is the foundation. Smart pointers express ownership. Raw pointers mean "non-owning."
|
|
4
|
+
|
|
5
|
+
## RAII (Resource Acquisition Is Initialization)
|
|
6
|
+
|
|
7
|
+
```cpp
|
|
8
|
+
// The single most important C++ idiom
|
|
9
|
+
// Resource lifetime = object lifetime
|
|
10
|
+
class DatabaseConnection {
|
|
11
|
+
sqlite3* db_ = nullptr;
|
|
12
|
+
|
|
13
|
+
public:
|
|
14
|
+
explicit DatabaseConnection(const std::string& path) {
|
|
15
|
+
if (sqlite3_open(path.c_str(), &db_) != SQLITE_OK) {
|
|
16
|
+
throw std::runtime_error("Failed to open database");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
~DatabaseConnection() {
|
|
21
|
+
if (db_) sqlite3_close(db_);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Non-copyable, movable
|
|
25
|
+
DatabaseConnection(const DatabaseConnection&) = delete;
|
|
26
|
+
DatabaseConnection& operator=(const DatabaseConnection&) = delete;
|
|
27
|
+
DatabaseConnection(DatabaseConnection&& other) noexcept
|
|
28
|
+
: db_{std::exchange(other.db_, nullptr)} {}
|
|
29
|
+
DatabaseConnection& operator=(DatabaseConnection&& other) noexcept {
|
|
30
|
+
if (this != &other) {
|
|
31
|
+
if (db_) sqlite3_close(db_);
|
|
32
|
+
db_ = std::exchange(other.db_, nullptr);
|
|
33
|
+
}
|
|
34
|
+
return *this;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
// No cleanup code needed at call sites — ever
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Smart Pointers
|
|
41
|
+
|
|
42
|
+
### std::unique_ptr — Single Ownership
|
|
43
|
+
|
|
44
|
+
```cpp
|
|
45
|
+
// The default smart pointer. Zero overhead over raw pointer.
|
|
46
|
+
auto widget = std::make_unique<Widget>(42);
|
|
47
|
+
|
|
48
|
+
// Transfer ownership explicitly
|
|
49
|
+
auto new_owner = std::move(widget);
|
|
50
|
+
// widget is now nullptr — ownership transferred
|
|
51
|
+
|
|
52
|
+
// Custom deleters for C APIs
|
|
53
|
+
auto file = std::unique_ptr<FILE, decltype(&fclose)>(
|
|
54
|
+
fopen("data.txt", "r"), &fclose);
|
|
55
|
+
|
|
56
|
+
// Factory functions return unique_ptr
|
|
57
|
+
auto create_engine(const Config& cfg) -> std::unique_ptr<Engine> {
|
|
58
|
+
return std::make_unique<ConcreteEngine>(cfg);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### std::shared_ptr — Shared Ownership
|
|
63
|
+
|
|
64
|
+
```cpp
|
|
65
|
+
// Use only when ownership is genuinely shared (rare)
|
|
66
|
+
auto shared = std::make_shared<Resource>();
|
|
67
|
+
auto also_owns = shared; // Reference count incremented
|
|
68
|
+
|
|
69
|
+
// Weak references to break cycles
|
|
70
|
+
class Node {
|
|
71
|
+
std::vector<std::shared_ptr<Node>> children_;
|
|
72
|
+
std::weak_ptr<Node> parent_; // Doesn't prevent destruction
|
|
73
|
+
|
|
74
|
+
public:
|
|
75
|
+
auto parent() const -> std::shared_ptr<Node> {
|
|
76
|
+
return parent_.lock(); // Returns nullptr if parent destroyed
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Rules:
|
|
81
|
+
// - Prefer unique_ptr. Only use shared_ptr when multiple owners exist.
|
|
82
|
+
// - Use make_shared (single allocation for control block + object)
|
|
83
|
+
// - Never create shared_ptr from raw pointer if one already exists
|
|
84
|
+
// - Use weak_ptr to observe without owning
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Raw Pointers — Non-Owning References
|
|
88
|
+
|
|
89
|
+
```cpp
|
|
90
|
+
// Raw pointer = "I'm borrowing this, I don't own it"
|
|
91
|
+
void process(const Widget* widget) {
|
|
92
|
+
if (!widget) return;
|
|
93
|
+
widget->do_work();
|
|
94
|
+
// Do NOT delete widget — you don't own it
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Prefer references over pointers when null is not valid
|
|
98
|
+
void process(const Widget& widget) {
|
|
99
|
+
widget.do_work();
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## std::span — Non-Owning View (C++20)
|
|
104
|
+
|
|
105
|
+
```cpp
|
|
106
|
+
// View into contiguous memory — no ownership, no copies
|
|
107
|
+
void process(std::span<const int> data) {
|
|
108
|
+
for (auto val : data) {
|
|
109
|
+
// Works with vector, array, C array, etc.
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
std::vector<int> vec = {1, 2, 3, 4, 5};
|
|
114
|
+
process(vec); // Implicit conversion
|
|
115
|
+
process({vec.data() + 1, 3}); // Subspan
|
|
116
|
+
int arr[] = {1, 2, 3};
|
|
117
|
+
process(arr); // C arrays too
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Move Semantics
|
|
121
|
+
|
|
122
|
+
```cpp
|
|
123
|
+
class Buffer {
|
|
124
|
+
std::unique_ptr<uint8_t[]> data_;
|
|
125
|
+
size_t size_ = 0;
|
|
126
|
+
|
|
127
|
+
public:
|
|
128
|
+
// Move constructor — steal resources
|
|
129
|
+
Buffer(Buffer&& other) noexcept
|
|
130
|
+
: data_{std::move(other.data_)}
|
|
131
|
+
, size_{std::exchange(other.size_, 0)} {}
|
|
132
|
+
|
|
133
|
+
// Move assignment
|
|
134
|
+
Buffer& operator=(Buffer&& other) noexcept {
|
|
135
|
+
data_ = std::move(other.data_);
|
|
136
|
+
size_ = std::exchange(other.size_, 0);
|
|
137
|
+
return *this;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Rule of Five: if you define one, define all five
|
|
141
|
+
Buffer(const Buffer& other); // Copy constructor
|
|
142
|
+
Buffer& operator=(const Buffer& other); // Copy assignment
|
|
143
|
+
~Buffer() = default; // Destructor
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// Move from function return — no cost
|
|
147
|
+
auto create_buffer(size_t size) -> Buffer {
|
|
148
|
+
Buffer buf(size);
|
|
149
|
+
// ... fill buffer ...
|
|
150
|
+
return buf; // NRVO or move — never copies
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## The Rule of Zero/Five
|
|
155
|
+
|
|
156
|
+
```cpp
|
|
157
|
+
// Rule of Zero: prefer classes that need no custom special members
|
|
158
|
+
class UserService {
|
|
159
|
+
std::unique_ptr<UserRepository> repo_; // Handles its own cleanup
|
|
160
|
+
std::string name_; // Handles its own cleanup
|
|
161
|
+
|
|
162
|
+
// No destructor, no copy/move constructors needed — compiler generates correct ones
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Rule of Five: if you need one, you need all five
|
|
166
|
+
// (destructor, copy ctor, copy assignment, move ctor, move assignment)
|
|
167
|
+
|
|
168
|
+
// Rule of Three (legacy): if you need destructor, you need copy ctor + copy assignment
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Memory Safety Checklist
|
|
172
|
+
|
|
173
|
+
```cpp
|
|
174
|
+
// 1. No owning raw pointers
|
|
175
|
+
Widget* w = new Widget(); // BUG: who deletes this?
|
|
176
|
+
|
|
177
|
+
// 2. No manual memory management
|
|
178
|
+
auto w = std::make_unique<Widget>(); // Correct
|
|
179
|
+
|
|
180
|
+
// 3. No dangling references
|
|
181
|
+
const std::string& get_name() {
|
|
182
|
+
std::string name = "Alice";
|
|
183
|
+
return name; // BUG: dangling reference to local
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// 4. No use-after-move
|
|
187
|
+
auto buf = create_buffer(1024);
|
|
188
|
+
consume(std::move(buf));
|
|
189
|
+
buf.size(); // BUG: use after move
|
|
190
|
+
|
|
191
|
+
// 5. No out-of-bounds access
|
|
192
|
+
vec[vec.size()]; // BUG: one past the end
|
|
193
|
+
vec.at(i); // Bounds-checked alternative
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Anti-Patterns
|
|
197
|
+
|
|
198
|
+
```cpp
|
|
199
|
+
// Never: new without corresponding smart pointer
|
|
200
|
+
auto* p = new Widget(42);
|
|
201
|
+
// Use: auto p = std::make_unique<Widget>(42);
|
|
202
|
+
|
|
203
|
+
// Never: manual delete
|
|
204
|
+
delete p;
|
|
205
|
+
delete[] arr;
|
|
206
|
+
// Use: RAII, smart pointers, containers
|
|
207
|
+
|
|
208
|
+
// Never: owning raw pointers in classes
|
|
209
|
+
class Bad {
|
|
210
|
+
Widget* widget_; // Who owns this? When is it freed?
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
// Never: returning raw owning pointers
|
|
214
|
+
Widget* create_widget(); // Caller must remember to delete
|
|
215
|
+
// Use: std::unique_ptr<Widget> create_widget();
|
|
216
|
+
|
|
217
|
+
// Never: C-style memory management
|
|
218
|
+
malloc/free/realloc
|
|
219
|
+
// Use: containers, smart pointers, std::vector
|
|
220
|
+
```
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Modern C++ Language Features
|
|
2
|
+
|
|
3
|
+
C++17/20/23 features used deliberately. Every feature exists for safety, clarity, or performance.
|
|
4
|
+
|
|
5
|
+
## Core Type System
|
|
6
|
+
|
|
7
|
+
### auto and Type Deduction
|
|
8
|
+
|
|
9
|
+
```cpp
|
|
10
|
+
// Good: auto when the type is obvious from context
|
|
11
|
+
auto name = std::string{"Alice"};
|
|
12
|
+
auto count = static_cast<size_t>(items.size());
|
|
13
|
+
auto it = container.find(key);
|
|
14
|
+
auto ptr = std::make_unique<Widget>(42);
|
|
15
|
+
|
|
16
|
+
// Good: trailing return types for complex deductions
|
|
17
|
+
template <typename T, typename U>
|
|
18
|
+
auto add(T a, U b) -> decltype(a + b) {
|
|
19
|
+
return a + b;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Bad: auto when it obscures the type
|
|
23
|
+
auto result = process(data); // What is result? Reader must look up process()
|
|
24
|
+
// Prefer explicit type when clarity matters
|
|
25
|
+
ProcessResult result = process(data);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### std::optional
|
|
29
|
+
|
|
30
|
+
```cpp
|
|
31
|
+
// Return type for "might not exist"
|
|
32
|
+
std::optional<User> find_user(std::string_view email) {
|
|
33
|
+
auto it = users_.find(std::string{email});
|
|
34
|
+
if (it == users_.end()) return std::nullopt;
|
|
35
|
+
return it->second;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Usage
|
|
39
|
+
if (auto user = find_user(email); user.has_value()) {
|
|
40
|
+
process(*user);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Or with value_or
|
|
44
|
+
auto name = find_user(email)
|
|
45
|
+
.transform([](const User& u) { return u.name(); })
|
|
46
|
+
.value_or("Unknown");
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### std::variant
|
|
50
|
+
|
|
51
|
+
```cpp
|
|
52
|
+
// Type-safe union — the C++ discriminated union
|
|
53
|
+
using JsonValue = std::variant<
|
|
54
|
+
std::nullptr_t,
|
|
55
|
+
bool,
|
|
56
|
+
double,
|
|
57
|
+
std::string,
|
|
58
|
+
std::vector<JsonValue>,
|
|
59
|
+
std::map<std::string, JsonValue>>;
|
|
60
|
+
|
|
61
|
+
// Visit with overloaded lambdas
|
|
62
|
+
auto to_string(const JsonValue& value) -> std::string {
|
|
63
|
+
return std::visit(overloaded{
|
|
64
|
+
[](std::nullptr_t) { return std::string{"null"}; },
|
|
65
|
+
[](bool b) { return b ? std::string{"true"} : std::string{"false"}; },
|
|
66
|
+
[](double d) { return std::to_string(d); },
|
|
67
|
+
[](const std::string& s) { return "\"" + s + "\""; },
|
|
68
|
+
[](const auto&) { return std::string{"[complex]"}; }
|
|
69
|
+
}, value);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// The overloaded helper
|
|
73
|
+
template<class... Ts>
|
|
74
|
+
struct overloaded : Ts... { using Ts::operator()...; };
|
|
75
|
+
template<class... Ts>
|
|
76
|
+
overloaded(Ts...) -> overloaded<Ts...>;
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### std::expected (C++23)
|
|
80
|
+
|
|
81
|
+
```cpp
|
|
82
|
+
// Result type — like Rust's Result
|
|
83
|
+
enum class ParseError { empty_input, invalid_format, out_of_range };
|
|
84
|
+
|
|
85
|
+
auto parse_port(std::string_view input) -> std::expected<uint16_t, ParseError> {
|
|
86
|
+
if (input.empty()) return std::unexpected{ParseError::empty_input};
|
|
87
|
+
|
|
88
|
+
int value = 0;
|
|
89
|
+
auto [ptr, ec] = std::from_chars(input.data(), input.data() + input.size(), value);
|
|
90
|
+
|
|
91
|
+
if (ec != std::errc{}) return std::unexpected{ParseError::invalid_format};
|
|
92
|
+
if (value < 1 || value > 65535) return std::unexpected{ParseError::out_of_range};
|
|
93
|
+
|
|
94
|
+
return static_cast<uint16_t>(value);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Monadic operations
|
|
98
|
+
auto result = parse_port(input)
|
|
99
|
+
.transform([](uint16_t port) { return Endpoint{"localhost", port}; })
|
|
100
|
+
.or_else([](ParseError e) -> std::expected<Endpoint, ParseError> {
|
|
101
|
+
return Endpoint{"localhost", 8080}; // Default
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Concepts (C++20)
|
|
106
|
+
|
|
107
|
+
```cpp
|
|
108
|
+
// Constrain templates at the interface, not in error messages
|
|
109
|
+
template <typename T>
|
|
110
|
+
concept Numeric = std::integral<T> || std::floating_point<T>;
|
|
111
|
+
|
|
112
|
+
template <typename T>
|
|
113
|
+
concept Serializable = requires(T t, std::ostream& os) {
|
|
114
|
+
{ os << t } -> std::same_as<std::ostream&>;
|
|
115
|
+
{ t.serialize() } -> std::convertible_to<std::string>;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// Clean constrained templates
|
|
119
|
+
template <Numeric T>
|
|
120
|
+
auto clamp(T value, T low, T high) -> T {
|
|
121
|
+
return std::max(low, std::min(value, high));
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Requires clause for complex constraints
|
|
125
|
+
template <typename Container>
|
|
126
|
+
requires std::ranges::range<Container> &&
|
|
127
|
+
std::totally_ordered<std::ranges::range_value_t<Container>>
|
|
128
|
+
auto find_median(Container& c) {
|
|
129
|
+
std::ranges::sort(c);
|
|
130
|
+
return c[c.size() / 2];
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Ranges (C++20/23)
|
|
135
|
+
|
|
136
|
+
```cpp
|
|
137
|
+
#include <ranges>
|
|
138
|
+
|
|
139
|
+
// Composable, lazy transformations
|
|
140
|
+
auto active_user_emails = users
|
|
141
|
+
| std::views::filter([](const User& u) { return u.is_active(); })
|
|
142
|
+
| std::views::transform([](const User& u) { return u.email(); })
|
|
143
|
+
| std::views::take(100);
|
|
144
|
+
|
|
145
|
+
// Collect into a container
|
|
146
|
+
auto result = active_user_emails | std::ranges::to<std::vector>();
|
|
147
|
+
|
|
148
|
+
// Algorithm with projection
|
|
149
|
+
std::ranges::sort(users, {}, &User::name); // Sort by name
|
|
150
|
+
auto it = std::ranges::find(users, target_id, &User::id); // Find by id
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Structured Bindings
|
|
154
|
+
|
|
155
|
+
```cpp
|
|
156
|
+
// Decompose aggregates
|
|
157
|
+
auto [key, value] = *map.find(target);
|
|
158
|
+
auto [x, y, z] = get_position();
|
|
159
|
+
|
|
160
|
+
// With if-init
|
|
161
|
+
if (auto [it, inserted] = map.try_emplace(key, value); !inserted) {
|
|
162
|
+
log::warn("Key {} already exists", key);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Iterate maps cleanly
|
|
166
|
+
for (const auto& [name, score] : scores) {
|
|
167
|
+
fmt::print("{}: {}\n", name, score);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## String Handling
|
|
172
|
+
|
|
173
|
+
```cpp
|
|
174
|
+
// std::string_view for non-owning references (C++17)
|
|
175
|
+
void process(std::string_view input) {
|
|
176
|
+
// Zero-copy substring
|
|
177
|
+
auto prefix = input.substr(0, 5);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// std::format (C++20)
|
|
181
|
+
auto msg = std::format("User {} logged in from {}", user.name(), ip_address);
|
|
182
|
+
|
|
183
|
+
// fmt library (pre-C++20 or for extra features)
|
|
184
|
+
fmt::print("Processing {} items\n", count);
|
|
185
|
+
|
|
186
|
+
// Never: manual snprintf or string concatenation in loops
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Anti-Patterns
|
|
190
|
+
|
|
191
|
+
```cpp
|
|
192
|
+
// Never: raw new/delete
|
|
193
|
+
auto* widget = new Widget(42);
|
|
194
|
+
delete widget;
|
|
195
|
+
// Use: auto widget = std::make_unique<Widget>(42);
|
|
196
|
+
|
|
197
|
+
// Never: C-style casts
|
|
198
|
+
int x = (int)some_double;
|
|
199
|
+
// Use: static_cast<int>(some_double)
|
|
200
|
+
|
|
201
|
+
// Never: NULL or 0 for null pointers
|
|
202
|
+
if (ptr == NULL)
|
|
203
|
+
// Use: if (ptr == nullptr)
|
|
204
|
+
|
|
205
|
+
// Never: C arrays in interfaces
|
|
206
|
+
void process(int* data, size_t len);
|
|
207
|
+
// Use: void process(std::span<const int> data);
|
|
208
|
+
|
|
209
|
+
// Never: using namespace std; in headers
|
|
210
|
+
// Pollutes every translation unit that includes the header
|
|
211
|
+
```
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# C++ Expert Overview
|
|
2
|
+
|
|
3
|
+
Principal-level C++ engineering. Deep language mastery, zero-cost abstractions, and systems-level thinking.
|
|
4
|
+
|
|
5
|
+
## Scope
|
|
6
|
+
|
|
7
|
+
This guide applies to:
|
|
8
|
+
- Systems programming (OS, drivers, embedded)
|
|
9
|
+
- High-performance computing and real-time systems
|
|
10
|
+
- Game engines and graphics programming
|
|
11
|
+
- Networking and server infrastructure
|
|
12
|
+
- Libraries and frameworks
|
|
13
|
+
- Scientific computing and simulation
|
|
14
|
+
|
|
15
|
+
## Core Philosophy
|
|
16
|
+
|
|
17
|
+
C++ gives you control. That control comes with responsibility. Write code that is correct, clear, and fast — in that order.
|
|
18
|
+
|
|
19
|
+
- **Resource management is automatic.** RAII is not optional — every resource has an owner, every owner has a destructor.
|
|
20
|
+
- **Zero-cost abstractions are the goal.** If an abstraction adds runtime overhead you don't need, you're using the wrong abstraction.
|
|
21
|
+
- **The type system is your strongest tool.** Use it to make invalid states unrepresentable at compile time.
|
|
22
|
+
- **Undefined behavior is a bug, period.** No shortcuts. No "it works on my machine." UB is the enemy.
|
|
23
|
+
- **Modern C++ is the baseline.** C++17 minimum, C++20/23 features where they improve clarity.
|
|
24
|
+
- **If you don't know, say so.** Admitting uncertainty about compiler behavior, ABI details, or standard wording is professional.
|
|
25
|
+
|
|
26
|
+
## Key Principles
|
|
27
|
+
|
|
28
|
+
1. **RAII Everywhere** — Every resource acquisition is an initialization, every release is a destruction
|
|
29
|
+
2. **Value Semantics by Default** — Copy, move, compare. References and pointers are the exception
|
|
30
|
+
3. **const Correctness** — If it doesn't mutate, it's `const`. No exceptions
|
|
31
|
+
4. **Prefer the Standard Library** — `std::vector`, `std::string`, `std::optional`, `std::variant` before rolling your own
|
|
32
|
+
5. **Compile-Time Over Runtime** — `constexpr`, `static_assert`, `concepts` — catch bugs before the program runs
|
|
33
|
+
|
|
34
|
+
## Project Structure
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
project/
|
|
38
|
+
├── include/mylib/ # Public headers
|
|
39
|
+
│ ├── mylib.hpp # Main include
|
|
40
|
+
│ ├── types.hpp
|
|
41
|
+
│ └── utils.hpp
|
|
42
|
+
├── src/ # Implementation files
|
|
43
|
+
│ ├── main.cpp
|
|
44
|
+
│ ├── types.cpp
|
|
45
|
+
│ └── utils.cpp
|
|
46
|
+
├── tests/ # Test files
|
|
47
|
+
│ ├── test_types.cpp
|
|
48
|
+
│ └── test_utils.cpp
|
|
49
|
+
├── benchmarks/ # Performance benchmarks
|
|
50
|
+
├── third_party/ # Vendored dependencies
|
|
51
|
+
├── cmake/ # CMake modules
|
|
52
|
+
│ └── CompilerWarnings.cmake
|
|
53
|
+
├── CMakeLists.txt
|
|
54
|
+
├── CMakePresets.json
|
|
55
|
+
├── .clang-format
|
|
56
|
+
├── .clang-tidy
|
|
57
|
+
└── conanfile.txt or vcpkg.json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Compiler Warnings
|
|
61
|
+
|
|
62
|
+
```cmake
|
|
63
|
+
# Treat warnings as errors — non-negotiable
|
|
64
|
+
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
65
|
+
$<$<CXX_COMPILER_ID:MSVC>:/W4 /WX /permissive->
|
|
66
|
+
$<$<NOT:$<CXX_COMPILER_ID:MSVC>>:-Wall -Wextra -Wpedantic -Werror
|
|
67
|
+
-Wshadow -Wconversion -Wsign-conversion -Wnon-virtual-dtor
|
|
68
|
+
-Wold-style-cast -Wcast-align -Wunused -Woverloaded-virtual
|
|
69
|
+
-Wnull-dereference -Wdouble-promotion -Wformat=2>
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Definition of Done
|
|
74
|
+
|
|
75
|
+
A C++ feature is complete when:
|
|
76
|
+
|
|
77
|
+
- [ ] Compiles with zero warnings under `-Wall -Wextra -Wpedantic -Werror`
|
|
78
|
+
- [ ] All tests pass (unit, integration)
|
|
79
|
+
- [ ] Sanitizers pass (ASan, UBSan, TSan)
|
|
80
|
+
- [ ] `clang-tidy` reports zero findings
|
|
81
|
+
- [ ] No undefined behavior (verified with sanitizers)
|
|
82
|
+
- [ ] No memory leaks (verified with ASan or Valgrind)
|
|
83
|
+
- [ ] `const` correctness enforced
|
|
84
|
+
- [ ] RAII used for all resource management
|
|
85
|
+
- [ ] No raw `new`/`delete` in application code
|
|
86
|
+
- [ ] Exception safety guarantees documented
|
|
87
|
+
- [ ] Code reviewed and approved
|