@chengzhao-dev/dsh-cpp-workflow 0.6.9 → 0.6.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +2 -2
- package/README.md +2 -2
- package/package.json +1 -1
- package/skills/building-cpp/assets/config/.clang-tidy +5 -3
- package/skills/building-cpp/assets/templates/projects/multi/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/multi/src/greeting.cpp +1 -1
- package/skills/building-cpp/assets/templates/projects/multi/src/main.cpp +1 -1
- package/skills/building-cpp/assets/templates/projects/shared-library/CMakeLists.txt +0 -1
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/greeting.cpp +1 -1
- package/skills/building-cpp/assets/templates/projects/shared-library/src/main.cpp +1 -1
- package/skills/building-cpp/assets/templates/projects/static-library/CMakeLists.txt +0 -1
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/CMakeLists.txt +1 -1
- package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/greeting.cpp +1 -1
- package/skills/building-cpp/assets/templates/projects/static-library/src/main.cpp +1 -1
- package/skills/building-cpp/examples/tooling.md +18 -0
- package/skills/building-cpp/references/standards/c++17/README.md +2 -1
- package/skills/building-cpp/references/standards/c++20/README.md +1 -0
- package/skills/configuring-cmake/references/cmake.md +2 -2
- package/skills/developing-cpp/examples/structure.md +1 -1
- package/skills/developing-cpp/references/declaration-order.md +9 -0
- package/skills/developing-cpp/references/file-template.md +3 -3
- package/skills/developing-cpp/references/google-cpp-style.md +2 -2
- package/skills/developing-cpp/references/layout.md +1 -1
- package/skills/developing-cpp/references/project-design.md +10 -0
- package/skills/developing-cpp/references/types.md +14 -7
- package/skills/developing-cpp/steps/02-boundary.md +1 -1
- package/skills/developing-cpp/steps/04-implementation.md +1 -1
package/README.en.md
CHANGED
|
@@ -19,13 +19,13 @@ The exception material follows the C++ Core Guidelines' Error handling section a
|
|
|
19
19
|
Pinned npm install:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.6.
|
|
22
|
+
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.6.11
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
The matching Git tag:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.6.
|
|
28
|
+
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.6.11
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
The desktop app owns the `desktop` profile. If the command-line `add` is rejected, add the plugin in the app settings and use the same pinned npm version. A Git tag install uses the prebuilt `lib/` committed in the repository and runs no build on the target machine; the package has no install script that needs approval.
|
package/README.md
CHANGED
|
@@ -19,13 +19,13 @@
|
|
|
19
19
|
npm 安装钉死版本:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.6.
|
|
22
|
+
dsh plugin --profile web add npm:@chengzhao-dev/dsh-cpp-workflow@0.6.11
|
|
23
23
|
```
|
|
24
24
|
|
|
25
25
|
同版本的 Git 标签:
|
|
26
26
|
|
|
27
27
|
```bash
|
|
28
|
-
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.6.
|
|
28
|
+
dsh plugin --profile web add github:chengzhao-dev/dsh-cpp-workflow#v0.6.11
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
桌面应用独占 `desktop` profile。命令行 `add` 被拒绝时,在应用设置里添加插件,地址填同一个 npm 版本。Git 标签安装使用仓库内已构建的 `lib/`,不在目标机器上重新构建;包内也不含需要授权执行的安装脚本。
|
package/package.json
CHANGED
|
@@ -54,9 +54,11 @@ CheckOptions:
|
|
|
54
54
|
value: CamelCase
|
|
55
55
|
- key: readability-identifier-naming.GlobalConstantPrefix
|
|
56
56
|
value: 'k'
|
|
57
|
+
# 局部常量按变量命名:Google 只给静态存储期的常量加 k 前缀。
|
|
57
58
|
- key: readability-identifier-naming.LocalConstantCase
|
|
58
|
-
value:
|
|
59
|
-
- key: readability-identifier-naming.LocalConstantPrefix
|
|
60
|
-
value: 'k'
|
|
59
|
+
value: lower_case
|
|
61
60
|
- key: readability-identifier-naming.MacroDefinitionCase
|
|
62
61
|
value: UPPER_CASE
|
|
62
|
+
# 包含守卫按 Google 规则以 _H_ 结尾,UPPER_CASE 会把它判成多余下划线。
|
|
63
|
+
- key: readability-identifier-naming.MacroDefinitionIgnoredRegexp
|
|
64
|
+
value: '^[A-Z][A-Z0-9_]*_H_$'
|
|
@@ -10,7 +10,7 @@ add_executable(app
|
|
|
10
10
|
src/main.cpp
|
|
11
11
|
src/greeting.cpp
|
|
12
12
|
)
|
|
13
|
-
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
13
|
+
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
14
14
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
15
15
|
set_target_properties(app PROPERTIES
|
|
16
16
|
CXX_STANDARD 23
|
|
@@ -10,7 +10,6 @@ enable_testing()
|
|
|
10
10
|
add_subdirectory(greeting)
|
|
11
11
|
|
|
12
12
|
add_executable(app src/main.cpp)
|
|
13
|
-
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
14
13
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
15
14
|
set_target_properties(app PROPERTIES
|
|
16
15
|
CXX_STANDARD 23
|
package/skills/building-cpp/assets/templates/projects/shared-library/greeting/CMakeLists.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
add_library(greeting SHARED src/greeting.cpp)
|
|
2
|
-
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
|
2
|
+
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
3
3
|
target_compile_features(greeting PUBLIC cxx_std_23)
|
|
4
4
|
set_target_properties(greeting PROPERTIES
|
|
5
5
|
CXX_STANDARD 23
|
|
@@ -10,7 +10,6 @@ enable_testing()
|
|
|
10
10
|
add_subdirectory(greeting)
|
|
11
11
|
|
|
12
12
|
add_executable(app src/main.cpp)
|
|
13
|
-
target_include_directories(app PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
|
14
13
|
target_compile_features(app PRIVATE cxx_std_23)
|
|
15
14
|
set_target_properties(app PROPERTIES
|
|
16
15
|
CXX_STANDARD 23
|
package/skills/building-cpp/assets/templates/projects/static-library/greeting/CMakeLists.txt
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
add_library(greeting STATIC src/greeting.cpp)
|
|
2
|
-
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
|
2
|
+
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
3
3
|
target_compile_features(greeting PUBLIC cxx_std_23)
|
|
4
4
|
set_target_properties(greeting PROPERTIES
|
|
5
5
|
CXX_STANDARD 23
|
|
@@ -168,3 +168,21 @@ clang++ 18.1.8, clang-format 18.1.8, clang-tidy 18.1.8, clangd 18.1.8
|
|
|
168
168
|
```
|
|
169
169
|
|
|
170
170
|
同主版本;`--live` 会核对。Apple Clang 与 Homebrew 工具不同版本时,仍按同一 LLVM 主版本要求处理,不要强行降级或改声明绕过。
|
|
171
|
+
|
|
172
|
+
## 把标准差异当成检查项
|
|
173
|
+
|
|
174
|
+
**差**:
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
# .clang-tidy
|
|
178
|
+
Checks: 'google-*,misc-*'
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**好**:
|
|
182
|
+
|
|
183
|
+
```yaml
|
|
184
|
+
# .clang-tidy
|
|
185
|
+
Checks: '-*,google-*,readability-identifier-naming'
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
能不能写 `= default` 的比较运算符由语言标准决定,不是检查项的问题。`misc-non-private-member-variables-in-classes` 只在打开 `misc-*` 时出现;工作流基线不开这一族,工程配置要与基线相同,而不是给这条检查加忽略选项。
|
|
@@ -28,6 +28,7 @@
|
|
|
28
28
|
|
|
29
29
|
- 没有 concepts、ranges、`std::format`、`std::span`、`std::bit_cast`。
|
|
30
30
|
- 没有 `std::print`、`std::expected`、`std::stacktrace`。
|
|
31
|
+
- 没有 `= default` 的比较运算符。
|
|
31
32
|
- `std::filesystem` 在 GCC 8 需要额外链接 `stdc++fs`,GCC 9 起才稳定;不要把“语言核心达标”当成文件系统库也达标。
|
|
32
33
|
|
|
33
34
|
## CMake
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
|
|
43
44
|
## 降档/升级
|
|
44
45
|
|
|
45
|
-
从 C++20 降到这里时,把 concepts 改成 `enable_if`/重载,把 ranges 改成迭代器算法,把 `std::format` 改成 `std::ostringstream
|
|
46
|
+
从 C++20 降到这里时,把 concepts 改成 `enable_if`/重载,把 ranges 改成迭代器算法,把 `std::format` 改成 `std::ostringstream`,把 `= default` 的比较运算符改回结构体外的手写自由函数。升级到 C++20 后先确认 `std::format` 的库门槛(libstdc++ 13+ / libc++ 14+),不要只看编译器版本。
|
|
46
47
|
|
|
47
48
|
## 验证
|
|
48
49
|
|
|
@@ -54,12 +54,12 @@ target_link_libraries(app PRIVATE greeting)
|
|
|
54
54
|
```cmake
|
|
55
55
|
# greeting/CMakeLists.txt
|
|
56
56
|
add_library(greeting STATIC src/greeting.cpp)
|
|
57
|
-
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
|
57
|
+
target_include_directories(greeting PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
|
|
58
58
|
CompileSettings_SetCxxStandard(greeting PUBLIC c++23)
|
|
59
59
|
CompileSettings_SetWarnings(greeting PRIVATE LEVEL standard)
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
- 库的 `PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}
|
|
62
|
+
- 库的 `PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include` 让程序与链接它的测试写 `#include "greeting.h"` 就能找到公共头,不需要各自再写 include 路径。
|
|
63
63
|
- 标准用 `CompileSettings_SetCxxStandard`:库用 `PUBLIC` 传播,程序用 `PRIVATE`;函数内部同时写 `target_compile_features` 与 `CXX_STANDARD` 三属性。
|
|
64
64
|
- `CXX_STANDARD_REQUIRED ON` 防止 CMake 在编译器不支持时静默 decay;`CXX_EXTENSIONS OFF` 把 `-std=gnu++NN` 收成 `-std=c++NN`。configure 后检查 `compile_commands.json` 的最后一条 `-std=`。
|
|
65
65
|
- 程序 target 固定 `app`;库 target 用组件名。
|
|
@@ -41,6 +41,15 @@ class TaskTable {
|
|
|
41
41
|
- 用户声明的特殊成员函数集中放第 4 组;`= default` 也写出来,读者才知道是故意默认。
|
|
42
42
|
- 不要把数据成员插在函数之间;数据成员永远在最后一组。
|
|
43
43
|
|
|
44
|
+
### 其他函数的组内次序
|
|
45
|
+
|
|
46
|
+
Google、LLVM、OpenCV 都没有规定这一组内部的次序;本工作流补上:
|
|
47
|
+
|
|
48
|
+
- 开头是 `operator==`:成员默认比较和 `friend` 都放这里,然后才是谓词 `Is` / `Has` / `Can`、`Get`、普通函数按使用先后。`friend` 不再放到这一组末尾。
|
|
49
|
+
- 比较运算符的签名与 `[[nodiscard]]` 规则见 `references/types.md`,这里不另写一套。
|
|
50
|
+
- 同一类型上的谓词留在类内,不因为实现只转调公开函数就拆成类外自由函数。
|
|
51
|
+
- `friend` 类型仍跟其他类型放在一起,和 `friend` 函数不是同一组。
|
|
52
|
+
|
|
44
53
|
## 命名空间作用域的头文件
|
|
45
54
|
|
|
46
55
|
文件槽位与守卫名以 `references/file-template.md` 为准;本节只看命名空间作用域内的排列顺序。
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
#include <cstdint>
|
|
58
58
|
#include <vector>
|
|
59
59
|
|
|
60
|
-
#include "
|
|
60
|
+
#include "dependency.h"
|
|
61
61
|
|
|
62
62
|
namespace project {
|
|
63
63
|
|
|
@@ -101,11 +101,11 @@ class ThingTable {
|
|
|
101
101
|
/// @file thing_table.cpp
|
|
102
102
|
/// @brief 实现 ThingTable 的添加与查询。
|
|
103
103
|
|
|
104
|
-
#include "
|
|
104
|
+
#include "thing.h"
|
|
105
105
|
|
|
106
106
|
#include <algorithm>
|
|
107
107
|
|
|
108
|
-
#include "
|
|
108
|
+
#include "other.h"
|
|
109
109
|
|
|
110
110
|
namespace project {
|
|
111
111
|
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
- 头文件必须自包含:自己用到的类型、宏、标准库头都直接包含,不依赖调用方的包含顺序。
|
|
17
17
|
- `.cpp` 第一个包含自己的配对头,然后按下面的顺序包含。
|
|
18
18
|
- 包含顺序:配对头 → C 系统头 → C++ 标准库头 → 其他库头 → 本项目头。每组之间空一行,组内按字母序;不要依赖 `clang-format` 的 `IncludeCategories` 自定义分组,本项目不再覆盖 Google 预设。
|
|
19
|
-
-
|
|
19
|
+
- 本项目头用引号写裸文件名,例如 `#include "logging.h"`。构建时把该组件的 `include/` 加入 include 搜索路径(`target_include_directories(<target> PUBLIC .../include)`),不要写 `"base/logging.h"` 这种从源码根起的长路径。
|
|
20
20
|
- 公共头文件直接放在组件的 `include/` 下;不要为了「整齐」再加一层命名空间目录。
|
|
21
21
|
- 跨文件共享的常量用 `inline constexpr`,放在命名空间里并带 `k` 前缀;头文件里不要定义非 inline 的普通全局变量。
|
|
22
22
|
- 头文件里只放模板、`constexpr`、类内联小函数和声明;普通函数的函数体放 `.cpp`。
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
- 默认用花括号初始化:`int count{};`、`std::vector<int> values{1, 2, 3};`。只有需要对比、`auto` 推导或赋值语义时用 `=`;`name = {{` 只用于多行聚合常量表,单个对象和空初始化仍写 `count{}`;不要用 `()` 初始化普通对象。
|
|
55
55
|
- 类声明顺序:public → protected → private;类型与别名 → 静态常量 → 工厂 → 构造/赋值/析构 → 其他函数 → 数据成员。
|
|
56
56
|
- 用户声明的拷贝/移动/析构函数在头文件声明、在 `.cpp` 定义;只有零参数且默认实现足够时才写 `= default`。
|
|
57
|
-
- 查询成员函数标尾部 `const`;返回结果对象的 API 加 `[[nodiscard]]`,不要给所有非 `void`
|
|
57
|
+
- 查询成员函数标尾部 `const`;返回结果对象的 API 加 `[[nodiscard]]`,不要给所有非 `void` 函数机械添加。标注位置与 `friend` 的例外见 `references/types.md`「`[[nodiscard]]`」。
|
|
58
58
|
- 所有权优先 `std::unique_ptr`;没有共享所有权的理由时不用 `std::shared_ptr`。禁止裸 `new` / `delete`。
|
|
59
59
|
- 禁止 C 风格强制转换;用 `static_cast`、`const_cast`、`reinterpret_cast`、`std::bit_cast`,并让 `clang-tidy` 的 `google-readability-casting` 兜底。
|
|
60
60
|
- `.cpp` 里不需要外部引用的 `constexpr` 直接放具名命名空间;仅一个函数使用时才用函数内 `static constexpr`;函数和类型仍放匿名命名空间。
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<name>_test.cpp 通过公共接口测试
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
- 公共头直接放 `include/`
|
|
18
|
+
- 公共头直接放 `include/` 下,包含时写裸文件名,例如 `#include "task_list.h"`;不要写 `"task_list/include/task_list.h"` 这种从仓库根起的长路径,也不要写 `../` 相对路径。
|
|
19
19
|
- 私有头放 `src/`,不进入公共 include 根;测试不得包含私有头。
|
|
20
20
|
- 一个组件一个职责;组件名用 snake_case,和命名空间一致。
|
|
21
21
|
- 组件之间通过公共头依赖;不要用 `../other/src/private.h` 跨组件包含私有实现。
|
|
@@ -18,6 +18,16 @@
|
|
|
18
18
|
- 同一底层类型承载不同含义(米/秒、行/列)且容易混用时,用轻量强类型包装。
|
|
19
19
|
- 不为每个名词造类;只有出现行为、不变量或独立变化原因时才升级为 `class`。
|
|
20
20
|
|
|
21
|
+
### 取值的边界
|
|
22
|
+
|
|
23
|
+
- 封闭取值一次列全。格子的取值是空、X、O;不要把 X 和 O 做成不含空的棋子,再用空值表示空格。
|
|
24
|
+
- 位置是行和列,不是格子的另一种取值。胜负、轮到谁、已下过的序列属于棋盘或对局,不要塞进位置类型。
|
|
25
|
+
- 有不变量的格子用公开构造的类,默认是空,X 或 O 至多写入一次。私有构造函数只留给必须经过工厂才能建立的对象,不用来表达三种取值,也不用来藏起行和列。
|
|
26
|
+
- 一次写入能区分的失败都放进结果枚举。传入空取值是结果项,不抛异常。
|
|
27
|
+
- 只由某一个类型产生的结果枚举嵌在该类型里:格子的写入结果和对局的写入结果取值不同,不合成命名空间里的一个 `PlaceResult`。
|
|
28
|
+
- 尺寸是某个类型的事实时,写成该类型的 `static constexpr`,例如 `Board::kRowCount`;不要再造一个只做 `static_cast<std::size_t>` 的别名常量。
|
|
29
|
+
- 一个局面的结果只用一个枚举和一个查询。不要把满盘、终局和赢家拆成三个入口,再由调用方拼回去。
|
|
30
|
+
|
|
21
31
|
## 封闭状态与结果
|
|
22
32
|
|
|
23
33
|
- 状态用连续取值的 `enum class`:`kPending`、`kActive`、`kDone`。
|
|
@@ -31,23 +31,25 @@ int CountWide(const std::vector<int>& values) {
|
|
|
31
31
|
}
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
循环下标与容器大小都用 `std::size_t
|
|
34
|
+
循环下标与容器大小都用 `std::size_t`,避免混合比较。业务编号与坐标另按下面的约定。
|
|
35
35
|
|
|
36
36
|
## 项目对整型角色的约定
|
|
37
37
|
|
|
38
38
|
| 角色 | 类型 | 理由 |
|
|
39
39
|
| --- | --- | --- |
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
40
|
+
| 不能为负的尺寸、容器长度、`std::array` 长度 | `std::size_t` | 与 STL 和 NTTP 一致 |
|
|
41
|
+
| 坐标等允许表示范围外取值的下标 | `int` | 能表达负值;越界判断交给持有尺寸的类型 |
|
|
42
|
+
| 没有上面两种理由的整数 | `int` | 宽度足够,写起来最短 |
|
|
43
|
+
| 取值很少的 `enum class` 的底层类型 | `std::uint8_t` | 只表达取值集合和布局,不参与算术 |
|
|
43
44
|
|
|
45
|
+
- 协议、文件格式与跨平台布局仍用 `<cstdint>` 的定宽整数(如 `std::int32_t`);工程内普通代码不必写定宽类型。
|
|
44
46
|
- 不用裸 `int` 承担跨平台协议或布局;它的宽度不可预测。
|
|
45
47
|
- 不用 `std::uint8_t` / `std::uint16_t` 当业务编号;负值无法表达,整数提升还会制造意外。
|
|
46
48
|
- 有符号乘法进入容器长度前先显式拓宽,否则会触发 `bugprone-implicit-widening-of-multiplication-result`:
|
|
47
49
|
|
|
48
50
|
```cpp
|
|
49
|
-
inline constexpr
|
|
50
|
-
inline constexpr
|
|
51
|
+
inline constexpr int kBatchSize = 3;
|
|
52
|
+
inline constexpr int kItemsPerBatch = 3;
|
|
51
53
|
inline constexpr std::size_t kItemCount =
|
|
52
54
|
static_cast<std::size_t>(kBatchSize) * static_cast<std::size_t>(kItemsPerBatch);
|
|
53
55
|
std::array<TaskState, kItemCount> items_{};
|
|
@@ -62,7 +64,7 @@ std::array<TaskState, kItemCount> items_{};
|
|
|
62
64
|
- 枚举值只在类型作用域内可见:`TaskState::kPending`,不写 `kPending`。
|
|
63
65
|
- 与整数之间不发生隐式转换;需要编号时写 `static_cast<int>(state)`,只用于输出或既有接口。
|
|
64
66
|
- 同类型值可以比较和赋值;不能参与算术。
|
|
65
|
-
-
|
|
67
|
+
- 需要固定布局时写底层类型。编号要在头文件里直接读到,就逐个写出来,不靠第一项默认为 0:`enum class TaskState : std::uint8_t { kPending = 0, kActive = 1, kDone = 2 };`
|
|
66
68
|
|
|
67
69
|
约定:
|
|
68
70
|
|
|
@@ -70,6 +72,8 @@ std::array<TaskState, kItemCount> items_{};
|
|
|
70
72
|
- 封闭状态码默认写 `: std::uint8_t`;普通枚举用默认底层类型。
|
|
71
73
|
- 枚举值的行尾注释要么全写要么全不写;两种句式与禁止项见 `references/comments.md`「枚举项与 `struct` 短字段:两种句式」。
|
|
72
74
|
- 需要“编号”与“名字”两套表示时,写显式映射函数,例如 `TaskStateToName` / `TaskStateFromName`,不要在枚举和整数之间来回隐式转换。
|
|
75
|
+
- 编号按“失败优先”排:空状态或前置条件失败为 0,业务失败随后,成功放在最后。读取端因此可以先判 0,再决定是否继续。
|
|
76
|
+
- 编号只用于输出和既有接口;要从编号找回名字,仍走显式映射函数,不拿编号做算术。
|
|
73
77
|
|
|
74
78
|
## 强类型包装
|
|
75
79
|
|
|
@@ -111,6 +115,9 @@ class TaskBoard {
|
|
|
111
115
|
|
|
112
116
|
- 只给“结果携带信息、忽略会出错”的函数:查询型 `const` 成员与返回结果对象的 API。
|
|
113
117
|
- 不给所有非 `void` 函数机械添加;标注的价值来自稀缺。
|
|
118
|
+
- 写法位置:`[[nodiscard]]` 在返回类型前面,然后才是 `static` 或 `constexpr`;参数列表之后才是 `const`、`override`、`noexcept`。
|
|
119
|
+
- 类内 `friend` 不加 `[[nodiscard]]`:Clang 拒绝 `[[nodiscard]] friend`、`friend [[nodiscard]]` 和参数列表后的 `[[nodiscard]]`。不要再猜下一种写法。
|
|
120
|
+
- 运算符不加 `[[nodiscard]]`,成员与 `friend` 都一样。比较的参数不具名:成员写 `bool operator==(const T&) const = default`,`friend` 写 `friend bool operator==(const T&, const T&);`;注释不给这个不具名参数写 `@param`。
|
|
114
121
|
- 有意丢弃时写 `static_cast<void>(result)`,不要为此全局关闭警告。
|
|
115
122
|
- 测试里验证“必须处理结果”时,同时验证忽略能被编译器发现。
|
|
116
123
|
|
|
@@ -15,7 +15,7 @@ app 只做参数、输入输出和装配
|
|
|
15
15
|
|
|
16
16
|
- 库 target 不依赖终端、GUI、网络脚本或全局单例;它只接收值、返回值、在无法完成任务时抛异常。
|
|
17
17
|
- 程序 target 链接库,负责读参数、读标准输入、打印结果、把退出码翻译成进程退出码。
|
|
18
|
-
- 公共头文件直接放在组件的 `include/`
|
|
18
|
+
- 公共头文件直接放在组件的 `include/` 下,包含时写裸文件名,例如 `#include "task_list.h"`;由构建把该目录加入 include 搜索路径,不要写从仓库根起的长路径或 `../` 相对路径。
|
|
19
19
|
- 依赖方向从程序指向库。库不反向包含程序的 `cli.h`,也不引用 `main.cpp`。
|
|
20
20
|
- 测试放 `tests/`,测试 target 链接被测库;测试不复制库的实现。
|
|
21
21
|
- 只有一个可执行文件、没有复用需求时,可以不分库;一旦出现第二个调用方或测试需要直接调用,再拆库。
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- 不写 C 风格强制转换;用 `static_cast` / `std::bit_cast` 等具名转换。
|
|
18
18
|
- 所有权用 `std::unique_ptr`;没有共享所有权的理由时不用 `std::shared_ptr`。
|
|
19
19
|
- 只改注释时,不改可观察行为;只改实现时,不改公共声明。两者同时需要时,先改声明,再改实现。
|
|
20
|
-
- 清空成员数组:标准支持 ranges 时用 `std::ranges::fill(cells_ | std::views::join,
|
|
20
|
+
- 清空成员数组:标准支持 ranges 时用 `std::ranges::fill(cells_ | std::views::join, CellState::kEmpty)`;不支持时用 `for` 循环逐格赋 `kEmpty`。两种都不写 `cells_ = {}`,那依赖枚举零值恰好是 `kEmpty`。
|
|
21
21
|
- 默认构造只做「建立初值」且与 `Clear()` 同义时,构造函数调用 `Clear()`,不另设 `Init()`;类内 `cells_{}` 仍保留,让成员先有确定初值。
|
|
22
22
|
|
|
23
23
|
## 情况
|