red64-cli 0.5.0 → 0.6.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 +64 -58
- package/dist/components/screens/StartScreen.d.ts.map +1 -1
- package/dist/components/screens/StartScreen.js +2 -2
- package/dist/components/screens/StartScreen.js.map +1 -1
- package/dist/services/AgentInvoker.js +4 -4
- package/dist/services/AgentInvoker.js.map +1 -1
- package/dist/services/ClaudeHealthCheck.d.ts +5 -0
- package/dist/services/ClaudeHealthCheck.d.ts.map +1 -1
- package/dist/services/ClaudeHealthCheck.js +43 -5
- package/dist/services/ClaudeHealthCheck.js.map +1 -1
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -1
- package/dist/services/index.js.map +1 -1
- package/framework/stacks/c/code-quality.md +326 -0
- package/framework/stacks/c/coding-style.md +347 -0
- package/framework/stacks/c/conventions.md +513 -0
- package/framework/stacks/c/error-handling.md +350 -0
- package/framework/stacks/c/feedback.md +158 -0
- package/framework/stacks/c/memory-safety.md +408 -0
- package/framework/stacks/c/tech.md +122 -0
- package/framework/stacks/c/testing.md +472 -0
- package/framework/stacks/cpp/code-quality.md +282 -0
- package/framework/stacks/cpp/coding-style.md +363 -0
- package/framework/stacks/cpp/conventions.md +420 -0
- package/framework/stacks/cpp/error-handling.md +264 -0
- package/framework/stacks/cpp/feedback.md +104 -0
- package/framework/stacks/cpp/memory-safety.md +351 -0
- package/framework/stacks/cpp/tech.md +160 -0
- package/framework/stacks/cpp/testing.md +323 -0
- package/framework/stacks/java/code-quality.md +357 -0
- package/framework/stacks/java/coding-style.md +400 -0
- package/framework/stacks/java/conventions.md +437 -0
- package/framework/stacks/java/error-handling.md +408 -0
- package/framework/stacks/java/feedback.md +180 -0
- package/framework/stacks/java/tech.md +126 -0
- package/framework/stacks/java/testing.md +485 -0
- package/framework/stacks/javascript/async-patterns.md +216 -0
- package/framework/stacks/javascript/code-quality.md +182 -0
- package/framework/stacks/javascript/coding-style.md +293 -0
- package/framework/stacks/javascript/conventions.md +268 -0
- package/framework/stacks/javascript/error-handling.md +216 -0
- package/framework/stacks/javascript/feedback.md +80 -0
- package/framework/stacks/javascript/tech.md +114 -0
- package/framework/stacks/javascript/testing.md +209 -0
- package/framework/stacks/loco/code-quality.md +156 -0
- package/framework/stacks/loco/coding-style.md +247 -0
- package/framework/stacks/loco/error-handling.md +225 -0
- package/framework/stacks/loco/feedback.md +35 -0
- package/framework/stacks/loco/loco.md +342 -0
- package/framework/stacks/loco/structure.md +193 -0
- package/framework/stacks/loco/tech.md +129 -0
- package/framework/stacks/loco/testing.md +211 -0
- package/framework/stacks/rust/code-quality.md +370 -0
- package/framework/stacks/rust/coding-style.md +475 -0
- package/framework/stacks/rust/conventions.md +430 -0
- package/framework/stacks/rust/error-handling.md +399 -0
- package/framework/stacks/rust/feedback.md +152 -0
- package/framework/stacks/rust/memory-safety.md +398 -0
- package/framework/stacks/rust/tech.md +121 -0
- package/framework/stacks/rust/testing.md +528 -0
- package/package.json +14 -2
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Feedback Configuration
|
|
2
|
+
|
|
3
|
+
Project-specific commands for automated feedback during C++ implementation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Build Commands
|
|
8
|
+
|
|
9
|
+
Commands to build the project during implementation.
|
|
10
|
+
|
|
11
|
+
```yaml
|
|
12
|
+
# Primary build command (REQUIRED)
|
|
13
|
+
build: cmake --build build
|
|
14
|
+
|
|
15
|
+
# Configure (first time or after CMakeLists changes)
|
|
16
|
+
configure: cmake --preset default
|
|
17
|
+
|
|
18
|
+
# Clean build
|
|
19
|
+
clean_build: cmake --build build --clean-first
|
|
20
|
+
|
|
21
|
+
# Release build
|
|
22
|
+
build_release: cmake --preset release && cmake --build build-release
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Test Commands
|
|
28
|
+
|
|
29
|
+
Commands to run tests during implementation. The agent will use these to verify code changes.
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
# Primary test command (REQUIRED)
|
|
33
|
+
test: ctest --test-dir build --output-on-failure
|
|
34
|
+
|
|
35
|
+
# Run specific test suite
|
|
36
|
+
test_suite: ctest --test-dir build -R "{suite_name}" --output-on-failure
|
|
37
|
+
|
|
38
|
+
# Run with verbose output
|
|
39
|
+
test_verbose: ctest --test-dir build -V
|
|
40
|
+
|
|
41
|
+
# Run only unit tests
|
|
42
|
+
test_unit: ctest --test-dir build -L unit --output-on-failure
|
|
43
|
+
|
|
44
|
+
# Run only integration tests
|
|
45
|
+
test_integration: ctest --test-dir build -L integration --output-on-failure
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Linting Commands
|
|
51
|
+
|
|
52
|
+
Commands for code quality checks.
|
|
53
|
+
|
|
54
|
+
```yaml
|
|
55
|
+
# Primary lint command (clang-tidy)
|
|
56
|
+
lint: run-clang-tidy -p build
|
|
57
|
+
|
|
58
|
+
# Lint single file
|
|
59
|
+
lint_file: clang-tidy -p build {file}
|
|
60
|
+
|
|
61
|
+
# Lint with auto-fix
|
|
62
|
+
lint_fix: run-clang-tidy -p build -fix
|
|
63
|
+
|
|
64
|
+
# Static analysis with cppcheck
|
|
65
|
+
static_analysis: cppcheck --project=build/compile_commands.json --enable=all --error-exitcode=1
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Format Commands
|
|
71
|
+
|
|
72
|
+
Commands for code formatting.
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
# Format check (CI)
|
|
76
|
+
format_check: clang-format --dry-run --Werror $(find src include -name '*.cpp' -o -name '*.hpp')
|
|
77
|
+
|
|
78
|
+
# Format fix
|
|
79
|
+
format: clang-format -i $(find src include -name '*.cpp' -o -name '*.hpp')
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Sanitizer Builds
|
|
85
|
+
|
|
86
|
+
Commands for sanitizer-instrumented builds.
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
# ASan + UBSan build and test
|
|
90
|
+
test_asan: cmake --preset asan && cmake --build build-asan && ctest --test-dir build-asan --output-on-failure
|
|
91
|
+
|
|
92
|
+
# TSan build and test
|
|
93
|
+
test_tsan: cmake -B build-tsan -DCMAKE_CXX_FLAGS="-fsanitize=thread" && cmake --build build-tsan && ctest --test-dir build-tsan
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Notes
|
|
99
|
+
|
|
100
|
+
- Uses CMake as the build system with Ninja backend
|
|
101
|
+
- Requires `compile_commands.json` for clang-tidy (set `CMAKE_EXPORT_COMPILE_COMMANDS=ON`)
|
|
102
|
+
- vcpkg manifest mode for dependency management
|
|
103
|
+
- ASan and TSan cannot be combined; run as separate CI jobs
|
|
104
|
+
- Google Test is the primary test framework, CTest is the test runner
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
# Memory Safety
|
|
2
|
+
|
|
3
|
+
Patterns and practices for memory-safe modern C++. Leverage RAII, smart pointers, and non-owning views to eliminate manual memory management.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Ownership is explicit**: Every resource has exactly one owner, encoded in the type system
|
|
10
|
+
- **RAII everywhere**: Acquisition in constructors, release in destructors, no exceptions
|
|
11
|
+
- **Non-owning by default**: Functions that observe data take references, spans, or string_views
|
|
12
|
+
- **Zero raw owning pointers**: If you write `new`, wrap it immediately; prefer `make_unique`/`make_shared`
|
|
13
|
+
- **Ref**: C++ Core Guidelines R.1-R.37, F.7, F.15-F.17
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Smart Pointers
|
|
18
|
+
|
|
19
|
+
### std::unique_ptr -- Exclusive Ownership (CG: R.20)
|
|
20
|
+
|
|
21
|
+
```cpp
|
|
22
|
+
// GOOD: Factory returns unique ownership
|
|
23
|
+
std::unique_ptr<Connection> create_connection(const Config& config) {
|
|
24
|
+
auto conn = std::make_unique<Connection>(config.host(), config.port());
|
|
25
|
+
conn->authenticate(config.credentials());
|
|
26
|
+
return conn; // Moved automatically (NRVO or implicit move)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// GOOD: Transfer ownership via value parameter (CG: R.32)
|
|
30
|
+
class ConnectionPool {
|
|
31
|
+
public:
|
|
32
|
+
void add(std::unique_ptr<Connection> conn) {
|
|
33
|
+
connections_.push_back(std::move(conn));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private:
|
|
37
|
+
std::vector<std::unique_ptr<Connection>> connections_;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// GOOD: Custom deleter for C resources
|
|
41
|
+
auto file = std::unique_ptr<FILE, decltype(&fclose)>(
|
|
42
|
+
fopen("data.txt", "r"), &fclose);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### std::shared_ptr -- Shared Ownership (CG: R.20, R.21)
|
|
46
|
+
|
|
47
|
+
```cpp
|
|
48
|
+
// GOOD: Use only when multiple owners genuinely need the resource
|
|
49
|
+
class EventSystem {
|
|
50
|
+
public:
|
|
51
|
+
void subscribe(std::shared_ptr<Handler> handler) {
|
|
52
|
+
handlers_.push_back(handler);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private:
|
|
56
|
+
std::vector<std::shared_ptr<Handler>> handlers_;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// GOOD: Always create with make_shared (one allocation, exception-safe) (CG: R.22)
|
|
60
|
+
auto config = std::make_shared<Config>(load_config());
|
|
61
|
+
|
|
62
|
+
// BAD: Two separate allocations, potential leak if exception between them
|
|
63
|
+
std::shared_ptr<Config> config(new Config(load_config()));
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### std::weak_ptr -- Breaking Cycles (CG: R.24)
|
|
67
|
+
|
|
68
|
+
```cpp
|
|
69
|
+
// GOOD: Break circular references with weak_ptr
|
|
70
|
+
class TreeNode {
|
|
71
|
+
public:
|
|
72
|
+
void set_parent(std::shared_ptr<TreeNode> parent) {
|
|
73
|
+
parent_ = parent; // weak_ptr does not extend lifetime
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
std::shared_ptr<TreeNode> parent() const {
|
|
77
|
+
return parent_.lock(); // Returns nullptr if parent is gone
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
private:
|
|
81
|
+
std::weak_ptr<TreeNode> parent_;
|
|
82
|
+
std::vector<std::shared_ptr<TreeNode>> children_;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
// GOOD: Cache pattern with weak_ptr
|
|
86
|
+
class TextureCache {
|
|
87
|
+
public:
|
|
88
|
+
std::shared_ptr<Texture> get(const std::string& path) {
|
|
89
|
+
if (auto it = cache_.find(path); it != cache_.end()) {
|
|
90
|
+
if (auto tex = it->second.lock()) {
|
|
91
|
+
return tex; // Still alive
|
|
92
|
+
}
|
|
93
|
+
cache_.erase(it); // Expired, clean up
|
|
94
|
+
}
|
|
95
|
+
auto tex = std::make_shared<Texture>(load_texture(path));
|
|
96
|
+
cache_[path] = tex;
|
|
97
|
+
return tex;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private:
|
|
101
|
+
std::unordered_map<std::string, std::weak_ptr<Texture>> cache_;
|
|
102
|
+
};
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## RAII Patterns
|
|
108
|
+
|
|
109
|
+
### Resource Wrapper Template
|
|
110
|
+
|
|
111
|
+
```cpp
|
|
112
|
+
// Generic RAII wrapper for C-style resources
|
|
113
|
+
template <typename T, auto Deleter>
|
|
114
|
+
class UniqueResource {
|
|
115
|
+
public:
|
|
116
|
+
explicit UniqueResource(T resource) noexcept : resource_(resource) {}
|
|
117
|
+
~UniqueResource() { if (resource_) Deleter(resource_); }
|
|
118
|
+
|
|
119
|
+
UniqueResource(const UniqueResource&) = delete;
|
|
120
|
+
UniqueResource& operator=(const UniqueResource&) = delete;
|
|
121
|
+
|
|
122
|
+
UniqueResource(UniqueResource&& other) noexcept
|
|
123
|
+
: resource_(std::exchange(other.resource_, T{})) {}
|
|
124
|
+
|
|
125
|
+
UniqueResource& operator=(UniqueResource&& other) noexcept {
|
|
126
|
+
if (this != &other) {
|
|
127
|
+
if (resource_) Deleter(resource_);
|
|
128
|
+
resource_ = std::exchange(other.resource_, T{});
|
|
129
|
+
}
|
|
130
|
+
return *this;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
[[nodiscard]] T get() const noexcept { return resource_; }
|
|
134
|
+
explicit operator bool() const noexcept { return resource_ != T{}; }
|
|
135
|
+
|
|
136
|
+
private:
|
|
137
|
+
T resource_;
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// Usage
|
|
141
|
+
using FileHandle = UniqueResource<FILE*, fclose>;
|
|
142
|
+
using SocketHandle = UniqueResource<int, close>;
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Scope Guards
|
|
146
|
+
|
|
147
|
+
```cpp
|
|
148
|
+
// RAII scope guard for ad-hoc cleanup
|
|
149
|
+
class ScopeGuard {
|
|
150
|
+
public:
|
|
151
|
+
explicit ScopeGuard(std::function<void()> cleanup)
|
|
152
|
+
: cleanup_(std::move(cleanup)) {}
|
|
153
|
+
~ScopeGuard() { if (cleanup_) cleanup_(); }
|
|
154
|
+
|
|
155
|
+
ScopeGuard(const ScopeGuard&) = delete;
|
|
156
|
+
ScopeGuard& operator=(const ScopeGuard&) = delete;
|
|
157
|
+
|
|
158
|
+
void dismiss() noexcept { cleanup_ = nullptr; }
|
|
159
|
+
|
|
160
|
+
private:
|
|
161
|
+
std::function<void()> cleanup_;
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Usage
|
|
165
|
+
void process() {
|
|
166
|
+
acquire_lock();
|
|
167
|
+
ScopeGuard guard([] { release_lock(); });
|
|
168
|
+
|
|
169
|
+
do_work(); // If this throws, lock is still released
|
|
170
|
+
guard.dismiss(); // Or: let it run anyway
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## Move Semantics and Perfect Forwarding
|
|
177
|
+
|
|
178
|
+
### Move Semantics (CG: C.64, F.18)
|
|
179
|
+
|
|
180
|
+
```cpp
|
|
181
|
+
// GOOD: Move-enable types that own resources
|
|
182
|
+
class Buffer {
|
|
183
|
+
public:
|
|
184
|
+
explicit Buffer(size_t size) : data_(new uint8_t[size]), size_(size) {}
|
|
185
|
+
|
|
186
|
+
// Move constructor: steal resources
|
|
187
|
+
Buffer(Buffer&& other) noexcept
|
|
188
|
+
: data_(std::exchange(other.data_, nullptr))
|
|
189
|
+
, size_(std::exchange(other.size_, 0)) {}
|
|
190
|
+
|
|
191
|
+
// Move assignment: release old, steal new
|
|
192
|
+
Buffer& operator=(Buffer&& other) noexcept {
|
|
193
|
+
if (this != &other) {
|
|
194
|
+
delete[] data_;
|
|
195
|
+
data_ = std::exchange(other.data_, nullptr);
|
|
196
|
+
size_ = std::exchange(other.size_, 0);
|
|
197
|
+
}
|
|
198
|
+
return *this;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
~Buffer() { delete[] data_; }
|
|
202
|
+
|
|
203
|
+
// Deleted copy (expensive, make explicit if needed)
|
|
204
|
+
Buffer(const Buffer&) = delete;
|
|
205
|
+
Buffer& operator=(const Buffer&) = delete;
|
|
206
|
+
|
|
207
|
+
private:
|
|
208
|
+
uint8_t* data_;
|
|
209
|
+
size_t size_;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// GOOD: Sink parameter -- take by value, then move (CG: F.18)
|
|
213
|
+
class MessageQueue {
|
|
214
|
+
public:
|
|
215
|
+
void push(std::string message) {
|
|
216
|
+
queue_.push_back(std::move(message)); // One move from parameter
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
private:
|
|
220
|
+
std::deque<std::string> queue_;
|
|
221
|
+
};
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Perfect Forwarding
|
|
225
|
+
|
|
226
|
+
```cpp
|
|
227
|
+
// GOOD: Forward arguments to preserve value category
|
|
228
|
+
template <typename... Args>
|
|
229
|
+
auto make_user(Args&&... args) {
|
|
230
|
+
return std::make_unique<User>(std::forward<Args>(args)...);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// GOOD: Emplace (constructs in-place, no temporary)
|
|
234
|
+
std::vector<User> users;
|
|
235
|
+
users.emplace_back("Alice", 30); // Constructs User directly in vector
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## Avoiding Dangling References
|
|
241
|
+
|
|
242
|
+
```cpp
|
|
243
|
+
// BAD: Dangling reference to local (CG: F.43)
|
|
244
|
+
std::string_view get_name() {
|
|
245
|
+
std::string name = "Alice";
|
|
246
|
+
return name; // DANGLING: name destroyed at end of scope
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// GOOD: Return by value
|
|
250
|
+
std::string get_name() {
|
|
251
|
+
std::string name = "Alice";
|
|
252
|
+
return name; // Moved or copy-elided (NRVO)
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// BAD: Reference to container element across mutation
|
|
256
|
+
auto& ref = vec[0];
|
|
257
|
+
vec.push_back(42); // May reallocate, invalidating ref
|
|
258
|
+
use(ref); // UNDEFINED BEHAVIOR
|
|
259
|
+
|
|
260
|
+
// GOOD: Use index or re-fetch after modification
|
|
261
|
+
vec.push_back(42);
|
|
262
|
+
use(vec[0]);
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Non-Owning Views: span and string_view (CG: F.24, F.25)
|
|
268
|
+
|
|
269
|
+
```cpp
|
|
270
|
+
// GOOD: string_view for read-only string parameters
|
|
271
|
+
void log_message(std::string_view message) {
|
|
272
|
+
spdlog::info("{}", message);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Accepts: string literals, std::string, char arrays -- zero copy
|
|
276
|
+
log_message("hello");
|
|
277
|
+
log_message(some_string);
|
|
278
|
+
log_message(some_string_view);
|
|
279
|
+
|
|
280
|
+
// GOOD: span for contiguous container parameters
|
|
281
|
+
double compute_average(std::span<const double> values) {
|
|
282
|
+
if (values.empty()) return 0.0;
|
|
283
|
+
return std::accumulate(values.begin(), values.end(), 0.0) / values.size();
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// Accepts: vector, array, C-style array -- zero copy
|
|
287
|
+
std::vector<double> vec = {1.0, 2.0, 3.0};
|
|
288
|
+
compute_average(vec);
|
|
289
|
+
compute_average(std::array{1.0, 2.0, 3.0});
|
|
290
|
+
double arr[] = {1.0, 2.0};
|
|
291
|
+
compute_average(arr);
|
|
292
|
+
|
|
293
|
+
// BAD: Storing string_view or span beyond the call
|
|
294
|
+
class Config {
|
|
295
|
+
std::string_view name_; // DANGER: may dangle if source string is destroyed
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
// GOOD: Store owning types as members
|
|
299
|
+
class Config {
|
|
300
|
+
std::string name_; // Owns its data
|
|
301
|
+
};
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
---
|
|
305
|
+
|
|
306
|
+
## Container Ownership Patterns
|
|
307
|
+
|
|
308
|
+
```cpp
|
|
309
|
+
// GOOD: Vector of unique_ptr for exclusive ownership of polymorphic objects
|
|
310
|
+
class ShapeCollection {
|
|
311
|
+
public:
|
|
312
|
+
void add(std::unique_ptr<Shape> shape) {
|
|
313
|
+
shapes_.push_back(std::move(shape));
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
void draw_all() const {
|
|
317
|
+
for (const auto& shape : shapes_) {
|
|
318
|
+
shape->draw();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
private:
|
|
323
|
+
std::vector<std::unique_ptr<Shape>> shapes_;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
// GOOD: std::optional for "maybe a value" without heap allocation
|
|
327
|
+
class UserProfile {
|
|
328
|
+
std::string name_;
|
|
329
|
+
std::optional<std::string> bio_; // No heap allocation for empty
|
|
330
|
+
std::optional<Address> address_; // Value semantics, not a pointer
|
|
331
|
+
};
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## Anti-Patterns
|
|
337
|
+
|
|
338
|
+
| Anti-Pattern | Problem | Correct Approach |
|
|
339
|
+
|---|---|---|
|
|
340
|
+
| `new` without smart pointer | Memory leak on exception | `std::make_unique` / `std::make_shared` |
|
|
341
|
+
| Raw owning pointer in class | Unclear ownership, leak-prone | `std::unique_ptr` member |
|
|
342
|
+
| `shared_ptr` everywhere | Performance overhead, unclear ownership | `unique_ptr` by default; `shared_ptr` only when shared |
|
|
343
|
+
| Storing `string_view` as member | Dangling reference if source destroyed | Store `std::string` as member |
|
|
344
|
+
| Reference to container element across mutation | Iterator/reference invalidation | Use index or re-fetch |
|
|
345
|
+
| Circular `shared_ptr` references | Memory leak (ref count never hits 0) | Break cycle with `weak_ptr` |
|
|
346
|
+
| `std::move` on const objects | Silently copies instead of moving | Remove const before move |
|
|
347
|
+
| Returning reference to local | Dangling reference, UB | Return by value |
|
|
348
|
+
|
|
349
|
+
---
|
|
350
|
+
|
|
351
|
+
_Memory safety in C++ is achieved through discipline and types. Let the compiler and RAII do the work; reserve raw pointers for non-owning observation only._
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# Technology Stack
|
|
2
|
+
|
|
3
|
+
Modern C++ application with safety-first design. C++20/23 as language standard, CMake for build system, vcpkg for dependency management, and comprehensive tooling for static analysis and sanitizers.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Core Technologies
|
|
8
|
+
|
|
9
|
+
- **Language**: C++20 (minimum), C++23 (preferred where supported)
|
|
10
|
+
- **Build System**: CMake 3.25+
|
|
11
|
+
- **Package Manager**: vcpkg (manifest mode) or Conan 2.x
|
|
12
|
+
- **Compiler**: GCC 13+, Clang 17+, or MSVC 17.8+
|
|
13
|
+
- **Standard Library**: libstdc++ or libc++
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Key Libraries
|
|
18
|
+
|
|
19
|
+
### Core Utilities
|
|
20
|
+
- **fmt**: Modern formatting library (std::format backport)
|
|
21
|
+
- **spdlog**: Fast, header-only logging (built on fmt)
|
|
22
|
+
- **nlohmann/json**: JSON for Modern C++
|
|
23
|
+
- **abseil-cpp**: Google's C++ common libraries (strings, time, hashing)
|
|
24
|
+
|
|
25
|
+
### Networking & Async
|
|
26
|
+
- **Boost.Asio** / **standalone Asio**: Async I/O and networking
|
|
27
|
+
- **gRPC**: High-performance RPC framework
|
|
28
|
+
- **cpp-httplib**: Single-header HTTP/HTTPS server and client
|
|
29
|
+
- **libcurl**: HTTP client (C library with C++ wrappers)
|
|
30
|
+
|
|
31
|
+
### Data & Storage
|
|
32
|
+
- **SQLite** (via sqlite_orm or sqlpp11): Embedded database
|
|
33
|
+
- **libpq** / **libpqxx**: PostgreSQL client
|
|
34
|
+
- **hiredis**: Redis client
|
|
35
|
+
|
|
36
|
+
### Concurrency
|
|
37
|
+
- **std::jthread** / **std::stop_token**: C++20 cooperative threading
|
|
38
|
+
- **std::latch** / **std::barrier**: C++20 synchronization primitives
|
|
39
|
+
- **Intel TBB**: Parallel algorithms and concurrent containers
|
|
40
|
+
|
|
41
|
+
### Testing
|
|
42
|
+
- **Google Test**: Test framework with rich assertions
|
|
43
|
+
- **Google Mock**: Mocking framework (bundled with Google Test)
|
|
44
|
+
- **Catch2 v3**: Alternative BDD-style test framework
|
|
45
|
+
- **Google Benchmark**: Microbenchmarking
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Build Systems
|
|
50
|
+
|
|
51
|
+
### CMake (Primary)
|
|
52
|
+
|
|
53
|
+
```cmake
|
|
54
|
+
cmake_minimum_required(VERSION 3.25)
|
|
55
|
+
project(myapp VERSION 1.0.0 LANGUAGES CXX)
|
|
56
|
+
|
|
57
|
+
set(CMAKE_CXX_STANDARD 23)
|
|
58
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
59
|
+
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
60
|
+
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
61
|
+
|
|
62
|
+
find_package(fmt CONFIG REQUIRED)
|
|
63
|
+
find_package(spdlog CONFIG REQUIRED)
|
|
64
|
+
find_package(GTest CONFIG REQUIRED)
|
|
65
|
+
|
|
66
|
+
add_executable(myapp src/main.cpp)
|
|
67
|
+
target_link_libraries(myapp PRIVATE fmt::fmt spdlog::spdlog)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Alternative Build Systems
|
|
71
|
+
|
|
72
|
+
| Build System | Use Case |
|
|
73
|
+
|---|---|
|
|
74
|
+
| **CMake** | Industry standard, broadest ecosystem support |
|
|
75
|
+
| **Meson** | Simpler syntax, fast builds, good for smaller projects |
|
|
76
|
+
| **Bazel** | Large monorepos, hermetic builds, Google-scale projects |
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Development Standards
|
|
81
|
+
|
|
82
|
+
### Code Quality
|
|
83
|
+
- **clang-format**: Automated code formatting
|
|
84
|
+
- **clang-tidy**: Static analysis and modernization checks
|
|
85
|
+
- **cppcheck**: Additional static analysis
|
|
86
|
+
- **include-what-you-use (IWYU)**: Header dependency hygiene
|
|
87
|
+
|
|
88
|
+
### Sanitizers
|
|
89
|
+
- **AddressSanitizer (ASan)**: Memory errors, buffer overflows, use-after-free
|
|
90
|
+
- **ThreadSanitizer (TSan)**: Data races and deadlocks
|
|
91
|
+
- **UndefinedBehaviorSanitizer (UBSan)**: Undefined behavior detection
|
|
92
|
+
- **MemorySanitizer (MSan)**: Uninitialized memory reads (Clang only)
|
|
93
|
+
|
|
94
|
+
### Security
|
|
95
|
+
- **Stack protector**: `-fstack-protector-strong`
|
|
96
|
+
- **Position-independent code**: `-fPIE -pie`
|
|
97
|
+
- **FORTIFY_SOURCE**: `-D_FORTIFY_SOURCE=2`
|
|
98
|
+
|
|
99
|
+
### Testing
|
|
100
|
+
- **Google Test**: Unit and integration tests
|
|
101
|
+
- **CTest**: CMake test runner
|
|
102
|
+
- **gcov / llvm-cov**: Code coverage
|
|
103
|
+
- **libFuzzer**: Fuzz testing
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Development Environment
|
|
108
|
+
|
|
109
|
+
### Required Tools
|
|
110
|
+
- C++20/23 compiler (GCC 13+, Clang 17+, or MSVC 17.8+)
|
|
111
|
+
- CMake 3.25+
|
|
112
|
+
- vcpkg or Conan 2.x
|
|
113
|
+
- clang-format, clang-tidy
|
|
114
|
+
- Ninja (recommended build backend)
|
|
115
|
+
|
|
116
|
+
### Common Commands
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
# Environment setup (vcpkg)
|
|
120
|
+
git clone https://github.com/microsoft/vcpkg.git
|
|
121
|
+
./vcpkg/bootstrap-vcpkg.sh
|
|
122
|
+
export VCPKG_ROOT=$(pwd)/vcpkg
|
|
123
|
+
|
|
124
|
+
# Configure and build
|
|
125
|
+
cmake --preset default # Or: cmake -B build -S .
|
|
126
|
+
cmake --build build # Build
|
|
127
|
+
ctest --test-dir build --output-on-failure # Run tests
|
|
128
|
+
|
|
129
|
+
# Code quality
|
|
130
|
+
clang-format -i src/**/*.cpp src/**/*.hpp # Format
|
|
131
|
+
run-clang-tidy -p build # Static analysis
|
|
132
|
+
cppcheck --project=build/compile_commands.json # Additional checks
|
|
133
|
+
|
|
134
|
+
# Sanitizer builds
|
|
135
|
+
cmake -B build-asan -DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
|
|
136
|
+
cmake --build build-asan
|
|
137
|
+
ctest --test-dir build-asan
|
|
138
|
+
|
|
139
|
+
# Package management (vcpkg manifest mode)
|
|
140
|
+
vcpkg new --application # Initialize manifest
|
|
141
|
+
vcpkg add port fmt spdlog nlohmann-json # Add dependencies
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Key Technical Decisions
|
|
147
|
+
|
|
148
|
+
| Decision | Rationale |
|
|
149
|
+
|---|---|
|
|
150
|
+
| **C++23 over C++17** | std::expected, std::print, improved ranges, deducing this |
|
|
151
|
+
| **CMake over Meson/Bazel** | Widest ecosystem support, vcpkg/Conan integration |
|
|
152
|
+
| **vcpkg over Conan** | Tighter CMake integration, simpler manifest mode, large registry |
|
|
153
|
+
| **fmt over printf/iostream** | Type-safe, fast, std::format compatible, no UB |
|
|
154
|
+
| **spdlog over custom logging** | Zero-cost when disabled, structured output, async support |
|
|
155
|
+
| **Google Test over Catch2** | Stronger mocking (gmock), wider CI integration, larger community |
|
|
156
|
+
| **Ninja over Make** | Parallel by default, faster incremental builds |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
_Document standards and patterns, not every dependency. See individual steering files for detailed conventions._
|