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,282 @@
|
|
|
1
|
+
# Code Quality Standards
|
|
2
|
+
|
|
3
|
+
Project memory for code quality conventions: formatting, static analysis, sanitizers, and compiler warnings in modern C++.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Shift left**: Catch bugs at compile time, not runtime
|
|
10
|
+
- **Automate enforcement**: clang-format and clang-tidy in CI, not code review
|
|
11
|
+
- **Warnings are errors**: `-Werror` in CI ensures nothing slips through
|
|
12
|
+
- **Sanitizers in test**: Run ASan/UBSan on every test run in CI
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## clang-format Configuration
|
|
17
|
+
|
|
18
|
+
### `.clang-format`
|
|
19
|
+
|
|
20
|
+
```yaml
|
|
21
|
+
BasedOnStyle: Google
|
|
22
|
+
Language: Cpp
|
|
23
|
+
Standard: c++20
|
|
24
|
+
ColumnLimit: 100
|
|
25
|
+
IndentWidth: 4
|
|
26
|
+
UseTab: Never
|
|
27
|
+
BreakBeforeBraces: Attach
|
|
28
|
+
AllowShortFunctionsOnASingleLine: Inline
|
|
29
|
+
AllowShortIfStatementsOnASingleLine: Never
|
|
30
|
+
AllowShortLoopsOnASingleLine: false
|
|
31
|
+
AlwaysBreakTemplateDeclarations: Yes
|
|
32
|
+
PointerAlignment: Left
|
|
33
|
+
SortIncludes: CaseSensitive
|
|
34
|
+
IncludeBlocks: Regroup
|
|
35
|
+
IncludeCategories:
|
|
36
|
+
- Regex: '^<[a-z_]+>' # C++ standard headers
|
|
37
|
+
Priority: 1
|
|
38
|
+
- Regex: '^<.+>' # Third-party headers
|
|
39
|
+
Priority: 2
|
|
40
|
+
- Regex: '^".*"' # Project headers
|
|
41
|
+
Priority: 3
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Format all source files
|
|
46
|
+
clang-format -i $(find src include -name '*.cpp' -o -name '*.hpp')
|
|
47
|
+
|
|
48
|
+
# Check formatting (CI)
|
|
49
|
+
clang-format --dry-run --Werror $(find src include -name '*.cpp' -o -name '*.hpp')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## clang-tidy Configuration
|
|
55
|
+
|
|
56
|
+
### `.clang-tidy`
|
|
57
|
+
|
|
58
|
+
```yaml
|
|
59
|
+
Checks: >
|
|
60
|
+
-*,
|
|
61
|
+
bugprone-*,
|
|
62
|
+
cert-*,
|
|
63
|
+
cppcoreguidelines-*,
|
|
64
|
+
misc-*,
|
|
65
|
+
modernize-*,
|
|
66
|
+
performance-*,
|
|
67
|
+
readability-*,
|
|
68
|
+
-modernize-use-trailing-return-type,
|
|
69
|
+
-readability-identifier-length,
|
|
70
|
+
-cppcoreguidelines-avoid-magic-numbers,
|
|
71
|
+
-readability-magic-numbers
|
|
72
|
+
|
|
73
|
+
WarningsAsErrors: >
|
|
74
|
+
bugprone-*,
|
|
75
|
+
modernize-use-nullptr,
|
|
76
|
+
modernize-use-override,
|
|
77
|
+
modernize-use-auto,
|
|
78
|
+
performance-unnecessary-copy-initialization,
|
|
79
|
+
performance-move-const-arg
|
|
80
|
+
|
|
81
|
+
CheckOptions:
|
|
82
|
+
- key: readability-identifier-naming.ClassCase
|
|
83
|
+
value: CamelCase
|
|
84
|
+
- key: readability-identifier-naming.FunctionCase
|
|
85
|
+
value: lower_case
|
|
86
|
+
- key: readability-identifier-naming.VariableCase
|
|
87
|
+
value: lower_case
|
|
88
|
+
- key: readability-identifier-naming.ConstantCase
|
|
89
|
+
value: CamelCase
|
|
90
|
+
- key: readability-identifier-naming.ConstantPrefix
|
|
91
|
+
value: k
|
|
92
|
+
- key: readability-identifier-naming.MemberSuffix
|
|
93
|
+
value: _
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Key Check Categories
|
|
97
|
+
|
|
98
|
+
| Category | Purpose | Example Checks |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| `modernize-*` | Upgrade to modern C++ | `use-auto`, `use-nullptr`, `use-override`, `use-ranges` |
|
|
101
|
+
| `performance-*` | Performance improvements | `unnecessary-copy-initialization`, `move-const-arg` |
|
|
102
|
+
| `bugprone-*` | Common bug patterns | `use-after-move`, `narrowing-conversions`, `dangling-handle` |
|
|
103
|
+
| `readability-*` | Code clarity | `identifier-naming`, `redundant-string-cstr` |
|
|
104
|
+
| `cppcoreguidelines-*` | C++ Core Guidelines | `owning-memory`, `no-malloc`, `slicing` |
|
|
105
|
+
| `cert-*` | CERT secure coding | `err33-c` (check return values), `str34-c` |
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
# Run clang-tidy (requires compile_commands.json)
|
|
109
|
+
run-clang-tidy -p build
|
|
110
|
+
|
|
111
|
+
# Single file
|
|
112
|
+
clang-tidy -p build src/main.cpp
|
|
113
|
+
|
|
114
|
+
# With auto-fix
|
|
115
|
+
run-clang-tidy -p build -fix
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## Compiler Warnings
|
|
121
|
+
|
|
122
|
+
### Recommended Flags
|
|
123
|
+
|
|
124
|
+
```cmake
|
|
125
|
+
# CMakeLists.txt
|
|
126
|
+
target_compile_options(myapp PRIVATE
|
|
127
|
+
$<$<CXX_COMPILER_ID:GNU,Clang,AppleClang>:
|
|
128
|
+
-Wall
|
|
129
|
+
-Wextra
|
|
130
|
+
-Wpedantic
|
|
131
|
+
-Werror
|
|
132
|
+
-Wconversion
|
|
133
|
+
-Wsign-conversion
|
|
134
|
+
-Wshadow
|
|
135
|
+
-Wnon-virtual-dtor
|
|
136
|
+
-Wold-style-cast
|
|
137
|
+
-Wcast-align
|
|
138
|
+
-Wunused
|
|
139
|
+
-Woverloaded-virtual
|
|
140
|
+
-Wmisleading-indentation
|
|
141
|
+
-Wnull-dereference
|
|
142
|
+
-Wdouble-promotion
|
|
143
|
+
-Wformat=2
|
|
144
|
+
-Wimplicit-fallthrough
|
|
145
|
+
>
|
|
146
|
+
$<$<CXX_COMPILER_ID:MSVC>:
|
|
147
|
+
/W4 /WX /permissive-
|
|
148
|
+
>
|
|
149
|
+
)
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
| Flag | Purpose |
|
|
153
|
+
|---|---|
|
|
154
|
+
| `-Wall -Wextra` | Enable most warnings |
|
|
155
|
+
| `-Wpedantic` | Enforce strict ISO C++ compliance |
|
|
156
|
+
| `-Werror` | Treat warnings as errors (CI only recommended) |
|
|
157
|
+
| `-Wshadow` | Warn on variable shadowing |
|
|
158
|
+
| `-Wconversion` | Warn on implicit narrowing conversions |
|
|
159
|
+
| `-Wnon-virtual-dtor` | Warn when base class has virtual functions but no virtual destructor |
|
|
160
|
+
| `-Wold-style-cast` | Flag C-style casts |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Sanitizers
|
|
165
|
+
|
|
166
|
+
### AddressSanitizer (ASan)
|
|
167
|
+
|
|
168
|
+
Detects: buffer overflows, use-after-free, use-after-scope, double-free, memory leaks.
|
|
169
|
+
|
|
170
|
+
```cmake
|
|
171
|
+
# CMake preset or option
|
|
172
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
|
173
|
+
set(CMAKE_LINKER_FLAGS "${CMAKE_LINKER_FLAGS} -fsanitize=address")
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### ThreadSanitizer (TSan)
|
|
177
|
+
|
|
178
|
+
Detects: data races, deadlocks.
|
|
179
|
+
|
|
180
|
+
```cmake
|
|
181
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=thread")
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### UndefinedBehaviorSanitizer (UBSan)
|
|
185
|
+
|
|
186
|
+
Detects: signed integer overflow, null pointer dereference, misaligned access, out-of-bounds shifts.
|
|
187
|
+
|
|
188
|
+
```cmake
|
|
189
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### MemorySanitizer (MSan) -- Clang Only
|
|
193
|
+
|
|
194
|
+
Detects: reads of uninitialized memory.
|
|
195
|
+
|
|
196
|
+
```cmake
|
|
197
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fno-omit-frame-pointer")
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Sanitizer CMake Preset Pattern
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{
|
|
204
|
+
"name": "asan",
|
|
205
|
+
"inherits": "debug",
|
|
206
|
+
"cacheVariables": {
|
|
207
|
+
"CMAKE_CXX_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer"
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
**Note**: ASan and TSan cannot be combined. Run them as separate CI jobs.
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
## Code Coverage
|
|
217
|
+
|
|
218
|
+
### gcov / llvm-cov
|
|
219
|
+
|
|
220
|
+
```cmake
|
|
221
|
+
# Coverage build
|
|
222
|
+
target_compile_options(myapp_tests PRIVATE --coverage)
|
|
223
|
+
target_link_options(myapp_tests PRIVATE --coverage)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# Generate coverage report
|
|
228
|
+
cmake --build build-coverage
|
|
229
|
+
ctest --test-dir build-coverage
|
|
230
|
+
llvm-cov report ./build-coverage/tests/myapp_tests \
|
|
231
|
+
-instr-profile=default.profdata \
|
|
232
|
+
-ignore-filename-regex='(test|third_party)/'
|
|
233
|
+
|
|
234
|
+
# HTML report
|
|
235
|
+
llvm-cov show ./build-coverage/tests/myapp_tests \
|
|
236
|
+
-instr-profile=default.profdata \
|
|
237
|
+
-format=html -output-dir=coverage-report/
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
## cppcheck (Supplementary)
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
# Run with compile database
|
|
246
|
+
cppcheck --project=build/compile_commands.json \
|
|
247
|
+
--enable=all \
|
|
248
|
+
--suppress=missingIncludeSystem \
|
|
249
|
+
--error-exitcode=1 \
|
|
250
|
+
--inline-suppr
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
---
|
|
254
|
+
|
|
255
|
+
## include-what-you-use (IWYU)
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Detect unnecessary or missing includes
|
|
259
|
+
iwyu_tool.py -p build -- -Xiwyu --mapping_file=iwyu.imp
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Quality Commands Summary
|
|
265
|
+
|
|
266
|
+
```bash
|
|
267
|
+
# Full quality check (CI pipeline)
|
|
268
|
+
clang-format --dry-run --Werror $(find src include -name '*.cpp' -o -name '*.hpp')
|
|
269
|
+
run-clang-tidy -p build
|
|
270
|
+
cppcheck --project=build/compile_commands.json --error-exitcode=1
|
|
271
|
+
cmake --build build-asan && ctest --test-dir build-asan
|
|
272
|
+
cmake --build build-coverage && ctest --test-dir build-coverage
|
|
273
|
+
|
|
274
|
+
# Development workflow
|
|
275
|
+
clang-format -i src/**/*.cpp src/**/*.hpp # Quick format
|
|
276
|
+
cmake --build build && ctest --test-dir build # Fast feedback
|
|
277
|
+
clang-tidy -p build src/app/my_file.cpp # Focused analysis
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
_Focus on patterns over exhaustive rules. Code should be formatted, analyzed, and tested under sanitizers._
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# C++ Coding Style
|
|
2
|
+
|
|
3
|
+
Coding style conventions beyond what clang-format enforces automatically. Opinionated patterns for readable, maintainable modern C++.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Philosophy
|
|
8
|
+
|
|
9
|
+
- **Safety by default**: Prefer constructs that prevent bugs at compile time
|
|
10
|
+
- **Value semantics first**: Copy/move values; use references for observation, pointers for optional observation
|
|
11
|
+
- **Const everything**: If it does not change, mark it `const`
|
|
12
|
+
- **Zero-cost abstractions**: Use templates and constexpr, not runtime polymorphism, when possible
|
|
13
|
+
- **Automate what you can**: Let clang-format handle layout; this doc covers judgment calls
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Naming Conventions
|
|
18
|
+
|
|
19
|
+
### Standard C++ Naming
|
|
20
|
+
|
|
21
|
+
| Element | Convention | Example |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| Classes, structs, enums | `PascalCase` | `UserService`, `HttpRequest` |
|
|
24
|
+
| Functions, methods | `snake_case` or `camelCase` (pick one, be consistent) | `get_user`, `getUser` |
|
|
25
|
+
| Variables, parameters | `snake_case` | `user_count`, `max_retries` |
|
|
26
|
+
| Constants (constexpr) | `kPascalCase` or `SCREAMING_SNAKE` | `kMaxRetries`, `MAX_RETRIES` |
|
|
27
|
+
| Macros (avoid) | `SCREAMING_SNAKE` | `MY_PROJECT_ASSERT` |
|
|
28
|
+
| Namespaces | `snake_case`, short | `myapp`, `myapp::net` |
|
|
29
|
+
| Template parameters | `PascalCase` | `T`, `Container`, `Predicate` |
|
|
30
|
+
| Member variables | `snake_case_` (trailing underscore) | `name_`, `connection_pool_` |
|
|
31
|
+
| Enum values | `PascalCase` or `kPascalCase` | `Color::Red`, `Status::kActive` |
|
|
32
|
+
|
|
33
|
+
### Naming Rules
|
|
34
|
+
|
|
35
|
+
```cpp
|
|
36
|
+
// GOOD: Descriptive, reveals intent
|
|
37
|
+
int active_user_count = get_active_users(db).size();
|
|
38
|
+
bool is_authenticated = token.has_value();
|
|
39
|
+
constexpr int kMaxRetryAttempts = 3;
|
|
40
|
+
|
|
41
|
+
std::expected<User, Error> find_user_by_email(std::string_view email);
|
|
42
|
+
|
|
43
|
+
class PaymentProcessor {
|
|
44
|
+
public:
|
|
45
|
+
void process_payment(const PaymentRequest& request);
|
|
46
|
+
private:
|
|
47
|
+
std::unique_ptr<Gateway> gateway_;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
// BAD: Abbreviated, unclear
|
|
51
|
+
int auc = get_au(db).size();
|
|
52
|
+
bool auth = tok.has_value();
|
|
53
|
+
#define N 3
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Boolean Naming
|
|
57
|
+
|
|
58
|
+
Prefix with `is_`, `has_`, `can_`, `should_`:
|
|
59
|
+
|
|
60
|
+
```cpp
|
|
61
|
+
bool is_active = true;
|
|
62
|
+
bool has_permission = check_access(user, resource);
|
|
63
|
+
bool can_publish = post.status() == Status::kDraft;
|
|
64
|
+
bool should_notify = user.preferences().notifications_enabled();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Modern C++ Idioms
|
|
70
|
+
|
|
71
|
+
### Rule of Zero (Prefer)
|
|
72
|
+
|
|
73
|
+
```cpp
|
|
74
|
+
// GOOD: Rule of Zero -- compiler-generated special members are correct
|
|
75
|
+
class UserService {
|
|
76
|
+
public:
|
|
77
|
+
explicit UserService(std::shared_ptr<UserRepo> repo)
|
|
78
|
+
: repo_(std::move(repo)) {}
|
|
79
|
+
|
|
80
|
+
// No destructor, copy/move constructors, or assignment operators needed.
|
|
81
|
+
// std::shared_ptr handles cleanup automatically.
|
|
82
|
+
|
|
83
|
+
private:
|
|
84
|
+
std::shared_ptr<UserRepo> repo_;
|
|
85
|
+
};
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Rule of Five (When Needed)
|
|
89
|
+
|
|
90
|
+
```cpp
|
|
91
|
+
// When managing a raw resource (rare -- prefer RAII wrappers)
|
|
92
|
+
class FileHandle {
|
|
93
|
+
public:
|
|
94
|
+
explicit FileHandle(const std::filesystem::path& path);
|
|
95
|
+
~FileHandle();
|
|
96
|
+
|
|
97
|
+
FileHandle(const FileHandle&) = delete;
|
|
98
|
+
FileHandle& operator=(const FileHandle&) = delete;
|
|
99
|
+
|
|
100
|
+
FileHandle(FileHandle&& other) noexcept;
|
|
101
|
+
FileHandle& operator=(FileHandle&& other) noexcept;
|
|
102
|
+
|
|
103
|
+
private:
|
|
104
|
+
int fd_ = -1;
|
|
105
|
+
};
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### Const Correctness (CG: Con.1-5)
|
|
109
|
+
|
|
110
|
+
```cpp
|
|
111
|
+
// GOOD: const by default
|
|
112
|
+
const auto user = find_user(user_id);
|
|
113
|
+
const auto& name = user.name();
|
|
114
|
+
|
|
115
|
+
void print_report(const std::vector<Record>& records); // Does not modify
|
|
116
|
+
|
|
117
|
+
class Cache {
|
|
118
|
+
public:
|
|
119
|
+
[[nodiscard]] std::optional<Value> get(std::string_view key) const;
|
|
120
|
+
void put(std::string key, Value value);
|
|
121
|
+
};
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Auto Usage Guidelines
|
|
127
|
+
|
|
128
|
+
### When to Use Auto
|
|
129
|
+
|
|
130
|
+
```cpp
|
|
131
|
+
// GOOD: Type is obvious from the right-hand side
|
|
132
|
+
auto user = std::make_unique<User>("Alice");
|
|
133
|
+
auto it = container.find(key);
|
|
134
|
+
auto [name, age] = get_person(); // Structured bindings
|
|
135
|
+
|
|
136
|
+
// GOOD: Long or complex types
|
|
137
|
+
auto callback = [](const Event& e) { handle(e); };
|
|
138
|
+
auto result = std::ranges::find_if(users, [](const auto& u) { return u.is_active(); });
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### When NOT to Use Auto
|
|
142
|
+
|
|
143
|
+
```cpp
|
|
144
|
+
// BAD: Type is not obvious
|
|
145
|
+
auto x = compute(); // What type is x?
|
|
146
|
+
auto val = get_value(); // int? double? string?
|
|
147
|
+
|
|
148
|
+
// GOOD: Be explicit when type is not clear from context
|
|
149
|
+
double temperature = compute_temperature(sensor_data);
|
|
150
|
+
std::string name = get_value("name");
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Range-Based For Loops and Structured Bindings
|
|
156
|
+
|
|
157
|
+
```cpp
|
|
158
|
+
// GOOD: Range-based for with const reference
|
|
159
|
+
for (const auto& user : users) {
|
|
160
|
+
process(user);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// GOOD: Structured bindings (C++17/20)
|
|
164
|
+
for (const auto& [key, value] : config_map) {
|
|
165
|
+
spdlog::info("{}={}", key, value);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// GOOD: With ranges (C++20)
|
|
169
|
+
auto active = users | std::views::filter(&User::is_active)
|
|
170
|
+
| std::views::transform(&User::name);
|
|
171
|
+
|
|
172
|
+
// BAD: Index-based when not needed
|
|
173
|
+
for (size_t i = 0; i < users.size(); ++i) {
|
|
174
|
+
process(users[i]);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Smart Pointer Usage
|
|
181
|
+
|
|
182
|
+
```cpp
|
|
183
|
+
// GOOD: unique_ptr by default for ownership (CG: R.20)
|
|
184
|
+
auto user = std::make_unique<User>("Alice", 30);
|
|
185
|
+
|
|
186
|
+
// GOOD: shared_ptr only when shared ownership is required (CG: R.20)
|
|
187
|
+
auto config = std::make_shared<Config>(load_config());
|
|
188
|
+
|
|
189
|
+
// GOOD: Raw pointer or reference for non-owning observation (CG: R.3)
|
|
190
|
+
void process(const User& user); // Guaranteed non-null
|
|
191
|
+
void process(const User* user); // May be null
|
|
192
|
+
|
|
193
|
+
// GOOD: Pass unique_ptr by value to transfer ownership (CG: R.32)
|
|
194
|
+
void register_user(std::unique_ptr<User> user);
|
|
195
|
+
|
|
196
|
+
// BAD: Raw owning pointer
|
|
197
|
+
User* user = new User("Alice", 30); // Who deletes this?
|
|
198
|
+
delete user; // Manual, error-prone
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Function Design
|
|
204
|
+
|
|
205
|
+
### Size and Parameter Limits
|
|
206
|
+
|
|
207
|
+
| Element | Guideline |
|
|
208
|
+
|---|---|
|
|
209
|
+
| Function body | Under 30 lines of logic, max 50 |
|
|
210
|
+
| Class | Under 300 lines, max 500 |
|
|
211
|
+
| Header file | Under 200 lines, max 400 |
|
|
212
|
+
| Source file | Under 500 lines, max 800 |
|
|
213
|
+
| Parameters | Max 5; use a struct/options for more |
|
|
214
|
+
|
|
215
|
+
### Prefer [[nodiscard]] (CG: F.48)
|
|
216
|
+
|
|
217
|
+
```cpp
|
|
218
|
+
// GOOD: Compiler warns if return value is ignored
|
|
219
|
+
[[nodiscard]] std::expected<User, Error> create_user(const CreateRequest& req);
|
|
220
|
+
[[nodiscard]] bool try_connect(std::string_view host, int port);
|
|
221
|
+
|
|
222
|
+
// GOOD: On classes returned from factories
|
|
223
|
+
class [[nodiscard]] ScopedLock { /* ... */ };
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### Early Returns with Guard Clauses
|
|
227
|
+
|
|
228
|
+
```cpp
|
|
229
|
+
// GOOD: Guard clauses
|
|
230
|
+
std::expected<Post, Error> publish(Post& post, const User& user) {
|
|
231
|
+
if (post.author_id() != user.id()) {
|
|
232
|
+
return std::unexpected(Error::kUnauthorized);
|
|
233
|
+
}
|
|
234
|
+
if (post.status() == Status::kPublished) {
|
|
235
|
+
return std::unexpected(Error::kAlreadyPublished);
|
|
236
|
+
}
|
|
237
|
+
if (post.body().empty()) {
|
|
238
|
+
return std::unexpected(Error::kValidation);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
post.set_status(Status::kPublished);
|
|
242
|
+
return post;
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
---
|
|
247
|
+
|
|
248
|
+
## Concepts (C++20)
|
|
249
|
+
|
|
250
|
+
```cpp
|
|
251
|
+
// GOOD: Constrain templates with concepts (CG: T.10)
|
|
252
|
+
template <std::integral T>
|
|
253
|
+
T safe_divide(T a, T b) {
|
|
254
|
+
if (b == 0) throw std::invalid_argument("division by zero");
|
|
255
|
+
return a / b;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// GOOD: Custom concepts for domain constraints
|
|
259
|
+
template <typename T>
|
|
260
|
+
concept Serializable = requires(T t, std::ostream& os) {
|
|
261
|
+
{ t.serialize(os) } -> std::same_as<void>;
|
|
262
|
+
{ T::deserialize(os) } -> std::same_as<T>;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
template <Serializable T>
|
|
266
|
+
void save(const T& obj, const std::filesystem::path& path);
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## Spaceship Operator (C++20)
|
|
272
|
+
|
|
273
|
+
```cpp
|
|
274
|
+
// GOOD: Auto-generates all comparison operators (CG: C.161)
|
|
275
|
+
struct Version {
|
|
276
|
+
int major;
|
|
277
|
+
int minor;
|
|
278
|
+
int patch;
|
|
279
|
+
|
|
280
|
+
auto operator<=>(const Version&) const = default;
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
// Usage: ==, !=, <, >, <=, >= all work automatically
|
|
284
|
+
assert(Version{1, 2, 0} < Version{1, 3, 0});
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## Anti-Patterns
|
|
290
|
+
|
|
291
|
+
### Raw new/delete
|
|
292
|
+
|
|
293
|
+
```cpp
|
|
294
|
+
// BAD: Manual memory management
|
|
295
|
+
Widget* w = new Widget();
|
|
296
|
+
// ... exception thrown here = memory leak
|
|
297
|
+
delete w;
|
|
298
|
+
|
|
299
|
+
// GOOD: RAII via smart pointers
|
|
300
|
+
auto w = std::make_unique<Widget>();
|
|
301
|
+
// Automatically cleaned up, even on exception
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### C-Style Casts
|
|
305
|
+
|
|
306
|
+
```cpp
|
|
307
|
+
// BAD: C-style cast -- hides intent, can do dangerous reinterpretations
|
|
308
|
+
void* data = get_data();
|
|
309
|
+
int* p = (int*)data;
|
|
310
|
+
|
|
311
|
+
// GOOD: Named casts express intent (CG: ES.49)
|
|
312
|
+
auto p = static_cast<int*>(data); // Known-safe conversion
|
|
313
|
+
auto p = dynamic_cast<Derived*>(base); // Runtime-checked downcast
|
|
314
|
+
auto p = reinterpret_cast<char*>(data); // Low-level, explicit danger
|
|
315
|
+
const_cast<int&>(ref) = 42; // Remove const (last resort)
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Macros for Constants
|
|
319
|
+
|
|
320
|
+
```cpp
|
|
321
|
+
// BAD: Macros have no scope, no type, cause hard-to-debug issues
|
|
322
|
+
#define MAX_SIZE 1024
|
|
323
|
+
#define PI 3.14159
|
|
324
|
+
|
|
325
|
+
// GOOD: constexpr has scope, type safety, debugger visibility (CG: ES.31)
|
|
326
|
+
constexpr int kMaxSize = 1024;
|
|
327
|
+
constexpr double kPi = 3.14159;
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Using Namespace in Headers
|
|
331
|
+
|
|
332
|
+
```cpp
|
|
333
|
+
// BAD: Pollutes every includer's namespace (CG: SF.7)
|
|
334
|
+
// my_header.hpp
|
|
335
|
+
using namespace std;
|
|
336
|
+
using namespace boost;
|
|
337
|
+
|
|
338
|
+
// GOOD: Fully qualify in headers; using-declarations in .cpp only
|
|
339
|
+
// my_header.hpp
|
|
340
|
+
std::vector<std::string> get_names();
|
|
341
|
+
|
|
342
|
+
// my_source.cpp
|
|
343
|
+
using std::vector;
|
|
344
|
+
using std::string;
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Passing Smart Pointers Unnecessarily
|
|
348
|
+
|
|
349
|
+
```cpp
|
|
350
|
+
// BAD: Function does not need ownership semantics
|
|
351
|
+
void print_name(const std::shared_ptr<User>& user) {
|
|
352
|
+
std::cout << user->name();
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// GOOD: Accept reference if you just observe (CG: R.36)
|
|
356
|
+
void print_name(const User& user) {
|
|
357
|
+
std::cout << user.name();
|
|
358
|
+
}
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
_Style is a tool for communication. Write code that your future self and teammates will thank you for._
|