@chengzhao-dev/dsh-cpp-workflow 0.1.1 → 0.2.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.
Files changed (80) hide show
  1. package/README.en.md +18 -15
  2. package/README.md +18 -15
  3. package/lib/index.js +7 -8
  4. package/lib/workspace.js +14 -14
  5. package/locale/en.json +1 -1
  6. package/locale/zh.json +1 -1
  7. package/package.json +5 -4
  8. package/skills/building-cpp/SKILL.md +6 -6
  9. package/skills/building-cpp/assets/config/.clang-format +3 -38
  10. package/skills/building-cpp/assets/config/.clang-tidy +8 -39
  11. package/skills/building-cpp/assets/config/.clangd +2 -5
  12. package/skills/building-cpp/assets/config/.vscode/extensions.json +2 -1
  13. package/skills/building-cpp/assets/config/.vscode/settings.json +16 -1
  14. package/skills/building-cpp/assets/templates/projects/common/running-build.sh +29 -18
  15. package/skills/building-cpp/assets/templates/projects/multi/CMakeLists.txt +9 -5
  16. package/skills/building-cpp/assets/templates/projects/multi/include/greeting.h +5 -3
  17. package/skills/building-cpp/assets/templates/projects/multi/src/greeting.cc +18 -0
  18. package/skills/building-cpp/assets/templates/projects/multi/src/main.cc +8 -0
  19. package/skills/building-cpp/assets/templates/projects/shared-library/CMakeLists.txt +8 -3
  20. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/CMakeLists.txt +15 -5
  21. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/include/greeting.h +5 -3
  22. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/greeting.cc +18 -0
  23. package/skills/building-cpp/assets/templates/projects/shared-library/src/main.cc +8 -0
  24. package/skills/building-cpp/assets/templates/projects/single/CMakeLists.txt +7 -3
  25. package/skills/building-cpp/assets/templates/projects/single/src/main.cc +15 -0
  26. package/skills/building-cpp/assets/templates/projects/static-library/CMakeLists.txt +8 -3
  27. package/skills/building-cpp/assets/templates/projects/static-library/greeting/CMakeLists.txt +15 -5
  28. package/skills/building-cpp/assets/templates/projects/static-library/greeting/include/greeting.h +5 -3
  29. package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/greeting.cc +18 -0
  30. package/skills/building-cpp/assets/templates/projects/static-library/src/main.cc +8 -0
  31. package/skills/building-cpp/examples/cmake.md +17 -17
  32. package/skills/building-cpp/examples/environment.md +4 -3
  33. package/skills/building-cpp/examples/tooling.md +31 -16
  34. package/skills/building-cpp/references/build-script.md +2 -2
  35. package/skills/building-cpp/references/cmake.md +35 -17
  36. package/skills/building-cpp/references/environment.md +17 -13
  37. package/skills/building-cpp/references/linking.md +6 -6
  38. package/skills/building-cpp/references/standards/README.md +165 -0
  39. package/skills/building-cpp/references/standards/c++11/README.md +50 -0
  40. package/skills/building-cpp/references/standards/c++11/cmake-snippet.cmake +7 -0
  41. package/skills/building-cpp/references/standards/c++14/README.md +48 -0
  42. package/skills/building-cpp/references/standards/c++14/cmake-snippet.cmake +7 -0
  43. package/skills/building-cpp/references/standards/c++17/README.md +49 -0
  44. package/skills/building-cpp/references/standards/c++17/cmake-snippet.cmake +7 -0
  45. package/skills/building-cpp/references/standards/c++20/README.md +49 -0
  46. package/skills/building-cpp/references/standards/c++20/cmake-snippet.cmake +7 -0
  47. package/skills/building-cpp/references/standards/c++23/README.md +50 -0
  48. package/skills/building-cpp/references/standards/c++23/cmake-snippet.cmake +7 -0
  49. package/skills/building-cpp/references/static-analysis.md +27 -15
  50. package/skills/building-cpp/scripts/checking-environment.mjs +21 -21
  51. package/skills/building-cpp/steps/01-build.md +10 -8
  52. package/skills/building-cpp/steps/02-tooling.md +9 -7
  53. package/skills/building-cpp/steps/03-check.md +4 -4
  54. package/skills/developing-cpp/SKILL.md +6 -6
  55. package/skills/developing-cpp/examples/comments.md +10 -8
  56. package/skills/developing-cpp/examples/exceptions.md +64 -45
  57. package/skills/developing-cpp/examples/naming.md +2 -2
  58. package/skills/developing-cpp/examples/structure.md +12 -9
  59. package/skills/developing-cpp/references/comments.md +10 -8
  60. package/skills/developing-cpp/references/declaration-order.md +7 -4
  61. package/skills/developing-cpp/references/exceptions.md +83 -46
  62. package/skills/developing-cpp/references/glossary.md +6 -6
  63. package/skills/developing-cpp/references/google-cpp-style.md +27 -37
  64. package/skills/developing-cpp/references/language.md +4 -4
  65. package/skills/developing-cpp/references/layout.md +14 -14
  66. package/skills/developing-cpp/references/naming.md +7 -6
  67. package/skills/developing-cpp/references/project-design.md +3 -3
  68. package/skills/developing-cpp/references/standard-library.md +1 -1
  69. package/skills/developing-cpp/steps/02-boundary.md +7 -7
  70. package/skills/developing-cpp/steps/03-declaration.md +9 -8
  71. package/skills/developing-cpp/steps/04-implementation.md +11 -7
  72. package/templates/cpp-workflow-project/SKILL.md +1 -1
  73. package/templates/cpp-workflow-project/environment.json +2 -1
  74. package/skills/building-cpp/assets/templates/projects/multi/src/greeting.cpp +0 -13
  75. package/skills/building-cpp/assets/templates/projects/multi/src/main.cpp +0 -8
  76. package/skills/building-cpp/assets/templates/projects/shared-library/greeting/src/greeting.cpp +0 -13
  77. package/skills/building-cpp/assets/templates/projects/shared-library/src/main.cpp +0 -8
  78. package/skills/building-cpp/assets/templates/projects/single/src/main.cpp +0 -9
  79. package/skills/building-cpp/assets/templates/projects/static-library/greeting/src/greeting.cpp +0 -13
  80. package/skills/building-cpp/assets/templates/projects/static-library/src/main.cpp +0 -8
@@ -1,20 +1,22 @@
1
1
  # 环境组合
2
2
 
3
- 环境是**声明**,不是探测结果。项目技能 `cpp-workflow-project` 的 `environment.json` 写清楚三个轴;构建规则、工具配置和检查都按这个声明执行。声明为空或组合非法时,先修声明,不要靠猜。
3
+ 环境是**声明**,不是探测结果。项目技能 `cpp-workflow-project` 的 `environment.json` 写清楚三个环境轴和一个语言标准;构建规则、工具配置和检查都按这个声明执行。声明为空或组合非法时,先修声明,不要靠猜。
4
4
 
5
- ## 三个轴
5
+ ## 四个轴
6
6
 
7
7
  | 轴 | 取值 | 说明 |
8
8
  | --- | --- | --- |
9
9
  | `host` | `windows` / `linux` / `macos` | 编辑器与代理壳所在的系统 |
10
10
  | `build_host` | `native` / `wsl` | 编译在哪执行;`wsl` 只对 `host=windows` 合法 |
11
11
  | `compiler` | `clang` / `gcc` | 一次只配一个;不支持 MSVC、clang-cl,也不把 C 编译器单独作为一个轴 |
12
+ | `standard` | `c++11` / `c++14` / `c++17` / `c++20` / `c++23` | 一个工程一个标准;新工程默认 `c++23`,旧声明缺字段时也按 `c++23` 处理 |
12
13
 
13
14
  ```json
14
15
  {
15
16
  "host": "windows",
16
17
  "build_host": "wsl",
17
- "compiler": "clang"
18
+ "compiler": "clang",
19
+ "standard": "c++23"
18
20
  }
19
21
  ```
20
22
 
@@ -24,8 +26,6 @@
24
26
  | --- | --- | --- | --- | --- |
25
27
  | windows | wsl | clang | 合法 | 是(WSL 内跑 POSIX 脚本) |
26
28
  | windows | wsl | gcc | 合法 | 是 |
27
- | windows | native | clang | 合法 | 否:缺 POSIX 壳(本版无 PowerShell 脚本) |
28
- | windows | native | gcc | 合法 | 否:缺 POSIX 壳(本版无 PowerShell 脚本) |
29
29
  | linux | native | clang | 合法 | 是 |
30
30
  | linux | native | gcc | 合法 | 是 |
31
31
  | macos | native | clang | 合法 | 是 |
@@ -33,12 +33,13 @@
33
33
 
34
34
  非法组合:
35
35
 
36
- - `host` 不是三个值之一,或 `build_host` / `compiler` 不是两个值之一。
37
- - 三个轴任意为空、缺失、写成数组或同时写两个值。
36
+ - `host`、`build_host`、`compiler` 不是各自允许的值,或 `standard` 不在 `c++11`–`c++23` 内。
37
+ - 三个环境轴任意为空、缺失、写成数组或同时写两个值;`standard` 缺失或为空时按默认 `c++23` 处理并给出提示(视为声明升级,不覆盖已写出的 `c++11`–`c++20`)。
38
38
  - `host=linux` / `host=macos` + `build_host=wsl`。
39
+ - `host=windows` + `build_host=native`:本版本不支持,静态校验直接返回失败。
39
40
  - `compiler=msvc`、`compiler=clang-cl`、`compiler=c`。
40
41
 
41
- `windows` + `native` 是合法声明,但本版本**没有** PowerShell 构建脚本。`--live` 会明确报告「缺的是 shell,不是编译器」;不要为了让它通过把 `build_host` 改成 `wsl`,也不要临时写一个脚本伪装成已支持。
42
+ `windows` + `native` 不再作为「合法但不能构建」的声明保留。声明校验直接返回 `ok: false`,`issues` 只有一句「本版本不能在 Windows 原生壳里构建」;不要建议改 WSL,也不要临时写 PowerShell 脚本伪装成已支持。
42
43
 
43
44
  ## 工具角色
44
45
 
@@ -56,11 +57,12 @@
56
57
 
57
58
  ## 版本与能力
58
59
 
59
- - **C++20**:编译器必须支持 `-std=c++20`;CMake ≥ 3.20(C++20 标准属性从 3.12 起可用)。
60
- - **clang-format / clang-tidy**:≥ 16。`BreakAfterAttributes` 在 16 才支持,15 及以下没有该选项。
60
+ - **标准**:新工程默认 C++23,可声明 `c++11`–`c++23`;编译器必须支持对应的 `-std=c++NN`。CMake ≥ 3.20;C++11/14 的 `cxx_std_*` 需要 CMake ≥ 3.8,但本工作流统一按 3.20 起步。`CXX_STANDARD_REQUIRED ON` 防止标准 decay;C++23 的库设施(如 `std::print`)以实际编译器/标准库为准。
61
+ - **clang-format / clang-tidy**:≥ 16。这是本工作流的工具基线;低于该版本时检查器报告具体角色和版本。
61
62
  - **clang 模式同版本**:`clang++`、`clang-format`、`clang-tidy`、`clangd` 必须是同一 LLVM 主版本。混装 17 的 clangd 与 18 的 clang-format 会出现诊断与格式化不一致。Apple Clang 也按这条核对;若工具版本对不上,报告的是具体角色和版本,不要为了通过而改声明。
62
- - **gcc 模式**:检查器不拿 GCC 的主版本去比 Clang 工具;`clang-format` / `clang-tidy` 仍要 ≥ 16,`clangd` 只要求可用。`g++` 必须是真的 GCC,不能是 Apple clang 的别名。GCC 需要自带 C++20 `<format>` 的标准库;版本过旧时先升级工具链,不要改检查器绕过。
63
+ - **gcc 模式**:检查器不拿 GCC 的主版本去比 Clang 工具;`clang-format` / `clang-tidy` 仍要 ≥ 16,`clangd` 只要求可用。`g++` 必须是真的 GCC,不能是 Apple clang 的别名。GCC 需要自带 C++23 `<print>` / `std::expected` 的标准库;版本过旧时先升级工具链,或把项目标准降到实际可用的档位,不要改检查器绕过。
63
64
  - **Apple Clang**:`/usr/bin/clang++` 通常是 Apple Clang;clangd 需能经 `xcrun` 找到 SDK。不要混用 Homebrew LLVM 与 Xcode 资源目录,也不要把 Homebrew 路径写死。
65
+ - **调试器**:VSCode 的 `CMake: Debug` 由 CMake Tools 调 C/C++ 扩展的 `cppdbg`;clang 模式要 `lldb`,gcc 模式要 `gdb`。调试器不在 `--live` 的编译器角色核对里,也不写进 `environment.json`;缺它时是调试启动失败,不是构建声明失败。
64
66
 
65
67
  ## 构建目录
66
68
 
@@ -76,7 +78,7 @@
76
78
 
77
79
  `<skill-dir>/scripts/checking-environment.mjs` 做两件事:
78
80
 
79
- 1. **静态**(默认):读 `environment.json`,检查三个轴和组合。轴为空或组合非法时以退出码 2 结束,不查找任何可执行文件。
81
+ 1. **静态**(默认):读 `environment.json`,检查三个环境轴、`standard` 和组合。轴为空或组合非法时以退出码 2 结束,不查找任何可执行文件。
80
82
  2. **活动**(`--live`):先做声明校验,再核对当前进程是否在声明的 build host 上,然后查 PATH、角色和版本。声明本身不合法时仍以退出码 2 结束;声明合法但活动核对失败时以退出码 3 结束。
81
83
 
82
84
  ```bash
@@ -89,7 +91,7 @@ node "<skill-dir>/scripts/checking-environment.mjs" --project . --live
89
91
  约束:
90
92
 
91
93
  - 只读:不安装、不下载、不改 PATH、不写项目文件。
92
- - `--live` 在 `host=windows` + `build_host=native` 下直接报告「缺 POSIX 壳;本版没有 PowerShell 构建脚本」,不继续找编译器。
94
+ - `--live` 在 `host=windows` + `build_host=native` 下不会继续:声明校验已经失败,错误是「本版本不能在 Windows 原生壳里构建」。
93
95
  - WSL 模式要求当前进程在 WSL 内(`WSL_DISTRO_NAME` / `WSL_INTEROP` 或 `/proc/version` 含 Microsoft);只在 Linux 上但不在 WSL 时失败。
94
96
  - macOS 上声明 `compiler=gcc` 时,`g++ --version` 若显示 Apple clang,按「不是真正的 GCC」失败。
95
97
  - 没有 `--live` 时不做任何 PATH 探测,CI 和 Windows 开发机都能做声明校验。
@@ -102,3 +104,5 @@ node "<skill-dir>/scripts/checking-environment.mjs" --project . --live
102
104
  | 2 | 声明缺失、轴为空、组合非法 |
103
105
  | 3 | 活动校验失败:不在声明的 build host、角色缺失、版本不符 |
104
106
  | 1 | 脚本自身错误:参数错误或内部异常 |
107
+
108
+ 各标准对应的编译器、库设施和工具档位见 [standards/README.md](standards/README.md)。
@@ -15,25 +15,25 @@
15
15
  - 链接:把多个目标文件和库合并,解析符号引用。`undefined reference` 在这一步失败。
16
16
  - 加载:程序启动时由动态加载器找到共享库;`error while loading shared libraries` 在这一步失败。
17
17
 
18
- `g++ -c file.cpp` 只编译不链接;`g++ file.o -o app` 只链接。`-E` 只看预处理,`-S` 只看汇编。
18
+ `g++ -c file.cc` 只编译不链接;`g++ file.o -o app` 只链接。`-E` 只看预处理,`-S` 只看汇编。
19
19
 
20
20
  ## 头文件、声明与定义
21
21
 
22
22
  - `#include` 是文本替换,不是模块导入;头文件只放声明、`inline` 定义、模板和 `constexpr` 定义。
23
- - 普通函数的定义放 `.cpp`;在头文件里写非 `inline` 函数定义,多个翻译单元包含时会重复定义。
24
- - 类定义放头文件;成员函数在类外定义时写 `ClassName::`,定义放 `.cpp`。
23
+ - 普通函数的定义放 `.cc`;在头文件里写非 `inline` 函数定义,多个翻译单元包含时会重复定义。
24
+ - 类定义放头文件;成员函数在类外定义时写 `ClassName::`,定义放 `.cc`。
25
25
  - 只用到声明时不要包含完整定义;前置声明可以减少编译依赖,但不能替代需要完整类型的场景(继承、成员对象、按值返回)。
26
- - 每个头文件自包含:单独编译一个只包含该头文件的 `.cpp` 应通过。用 `#pragma once` 防止重复包含。
26
+ - 每个头文件自包含:单独编译一个只包含该头文件的 `.cc` 应通过。用路径式 `#define` 守卫防止重复包含,不用 `#pragma once`。
27
27
 
28
28
  ## `undefined reference` 分诊
29
29
 
30
30
  | 现象 | 常见原因 | 修法 |
31
31
  | --- | --- | --- |
32
- | 链接器说某个成员函数未定义 | 声明了但没写定义,或 `.cpp` 没加入 target | 补定义,或把源文件加入 `target_sources` |
32
+ | 链接器说某个成员函数未定义 | 声明了但没写定义,或 `.cc` 没加入 target | 补定义,或把源文件加入 `target_sources` |
33
33
  | 只有某个平台失败 | 条件编译把定义排除了 | 检查宏和平台分支,保证每个平台都有定义 |
34
34
  | 第三方库符号缺失 | 没链接库,或库顺序不对 | `target_link_libraries` 加库;CMake 会处理顺序 |
35
35
  | C++ 符号被当成 C 符号 | 头文件缺少 `extern \"C\"` | C 接口头加 `extern \"C\"`,C++ 调用方也可见 |
36
- | 模板成员未定义 | 模板定义在 `.cpp`,实例化点看不到 | 模板定义移到头文件,或显式实例化 |
36
+ | 模板成员未定义 | 模板定义在 `.cc`,实例化点看不到 | 模板定义移到头文件,或显式实例化 |
37
37
  | 静态库中的目标文件没被拉入 | 链接器只取被引用符号所在的目标文件 | 确认符号确实被引用,或改用对象库/共享库 |
38
38
 
39
39
  先看链接器报的完整符号名和来源文件,不要只看第一行。
@@ -0,0 +1,165 @@
1
+ # 语言标准档案
2
+
3
+ 本工作流默认 **C++23**,但一个工程只选一个 `standard`,不为同一份源码承诺“同时兼容 C++11–C++23”。标准是项目级事实,写在 `.agents/skills/cpp-workflow-project/environment.json`。
4
+
5
+ 每个标准单独一个目录:`c++11/`、`c++14/`、`c++17/`、`c++20/`、`c++23/`。目录里放这一档自己的编译器下限、语言/库设施、CMake 片段和工具映射;模板仍然只有一套公共骨架,靠 `__cplusplus` 条件选择实现,不复制五份模板。
6
+
7
+ Google C++ Style Guide 上游仍写 “target C++20”,本工作流默认 C++23 是一处明确偏离;Google 的排版、命名、头文件和异常之外的规则不变。异常政策仍按 [exceptions.md](../../../developing-cpp/references/exceptions.md)。
8
+
9
+ ## 选择标准
10
+
11
+ | 标准 | 目录 | 一句话 |
12
+ | --- | --- | --- |
13
+ | C++11 | [c++11/README.md](c++11/README.md) | 老工具链、老库仍要维护时的最低档 |
14
+ | C++14 | [c++14/README.md](c++14/README.md) | 需要 `make_unique`、泛型 lambda,但还不想上 C++17 |
15
+ | C++17 | [c++17/README.md](c++17/README.md) | 需要 `string_view`、`optional`、`if constexpr` 的稳定基线 |
16
+ | C++20 | [c++20/README.md](c++20/README.md) | 需要 concepts、ranges、`std::format` 的现代基线 |
17
+ | C++23 | [c++23/README.md](c++23/README.md) | 本工作流默认;需要 `print`、`expected` 等设施时选它 |
18
+
19
+ 新工程写 `c++23`;已有工程按现有 `CMakeLists.txt` 和编译器能力选,不为了“统一”擅自升降。降档前先读对应目录的“不能假设”和“降档要改什么”。
20
+
21
+ ## 三个规划粒度
22
+
23
+ | 粒度 | 先看 | 产出 |
24
+ | --- | --- | --- |
25
+ | 项目 | 本页选择表、编译器/库门槛 | `environment.json` 的 `standard`,以及“为什么选这档” |
26
+ | target | 该档的 `cmake-snippet.cmake` | `cxx_std_*`、`CXX_STANDARD`、`CXX_STANDARD_REQUIRED`、`CXX_EXTENSIONS` |
27
+ | 代码/工具 | 该档 README 的“能用/不能假设/降档” | 设施替换、`.clang-format` 档位、`.clangd` 不写 `-std` |
28
+ | 验证 | 本页验证矩阵、`scripts/checking-standard-matrix.sh` | configure/build/CTest 和 `compile_commands.json` 的精确 `-std` |
29
+
30
+ 每个标准目录都按这四层写;不要只在项目层改 `standard`,却在 target 层留着 C++23 的 `cxx_std_23`。
31
+
32
+ ## 共用矩阵
33
+
34
+ | `standard` | CMake meta-feature | `CXX_STANDARD` | `__cplusplus` | clang-format 21/22 | 模板实用下限(含标准库设施) |
35
+ | --- | --- | --- | --- | --- | --- |
36
+ | `c++11` | `cxx_std_11` | 11 | `201103L` | `c++11` | GCC 4.8 / Clang 3.4 |
37
+ | `c++14` | `cxx_std_14` | 14 | `201402L` | `c++14` | GCC 5 / Clang 3.4 |
38
+ | `c++17` | `cxx_std_17` | 17 | `201703L` | `c++17` | GCC 7 / Clang 5 |
39
+ | `c++20` | `cxx_std_20` | 20 | `202002L` | `c++20` | GCC 13 / Clang 16(`std::format`) |
40
+ | `c++23` | `cxx_std_23` | 23 | `202302L` | `Latest` | GCC 13 / Clang 17(模板只用 `std::format`) |
41
+
42
+ “语言核心最低编译器”只保证语法和核心库;标准库设施要单独看:
43
+
44
+ | 设施 | 标准 | 额外门槛 |
45
+ | --- | --- | --- |
46
+ | `std::string_view`、`std::optional`、`std::variant`、`if constexpr` | C++17 | 随语言核心 |
47
+ | `std::format` | C++20 | libstdc++ 13+;libc++ 14+(特性宏到 19 才稳定) |
48
+ | `std::print`、`std::expected`、`std::stacktrace` | C++23 | `std::print`:libstdc++ 14+、libc++ 19+;`std::expected` 随各库 C++23 实现;`std::stacktrace` 还要链接对应库 |
49
+
50
+ Clang/GCC 的 “Partial” 状态意味着 C++23 不是全量实现。用到具体设施前,先查:
51
+
52
+ - [GCC C++ status](https://gcc.gnu.org/projects/cxx-status.html)
53
+ - [Clang C++ status](https://clang.llvm.org/cxx_status.html)
54
+ - [cppreference C++23 compiler support](https://en.cppreference.com/w/cpp/compiler_support/23)
55
+
56
+ ## 共用规则
57
+
58
+ ### CMake
59
+
60
+ 每个 target 同时写 meta-feature 和精确属性;片段见各标准目录的 `cmake-snippet.cmake`,把 target 名换成实际 target:
61
+
62
+ ```cmake
63
+ target_compile_features(app PRIVATE cxx_std_23)
64
+ set_target_properties(app PROPERTIES
65
+ CXX_STANDARD 23
66
+ CXX_STANDARD_REQUIRED ON
67
+ CXX_EXTENSIONS OFF
68
+ )
69
+ ```
70
+
71
+ - `cxx_std_23` 是“至少”,会向依赖它的 target 传播。
72
+ - `CXX_STANDARD` 是请求值;`CXX_STANDARD_REQUIRED ON` 防止编译器不支持时静默 decay。
73
+ - `CXX_EXTENSIONS OFF` 把 `-std=gnu++23` 收成 `-std=c++23`。
74
+ - configure 后读 `compile_commands.json` 的最后一个 `-std=`;必须是 `-std=c++NN`,不能是 `gnu++NN`。
75
+ - CMake 最低 3.20(模板统一要求);只单独使用低档片段时,C++11/14 的 `cxx_std_*` meta-feature 最低 3.8,C++20 为 3.12。C++23 的 `CXX_STANDARD 23` 自 3.20 才有。
76
+
77
+ ### clang-format
78
+
79
+ clang-format 21/22 的 `Standard` 只到 `c++20`。映射:
80
+
81
+ | 声明 | 配置 |
82
+ | --- | --- |
83
+ | `c++11`–`c++20` | 对应 `Standard: c++NN` |
84
+ | `c++23` | `Standard: Latest`(21/22 没有 `c++23`) |
85
+ | `c++26`(未来) | 工具支持时写 `c++26`,否则 `Latest` |
86
+
87
+ 不要为了“看起来精确”写 `c++23`;clang-format 21 会报 `unknown enumerated scalar` 并退出 1。
88
+
89
+ ### clangd
90
+
91
+ `.clangd` **不写 `-std`**。clangd 从 `compile_commands.json` 读标准;写死 `-std=c++20` 会把 C++23 工程降级,表现为 `<print>` 不存在、`if consteval` 解析失败。
92
+
93
+ 只保留:
94
+
95
+ ```yaml
96
+ CompileFlags:
97
+ CompilationDatabase: build/clang
98
+ ```
99
+
100
+ 切换编译器时改目录;没有数据库时先回到定构建生成。
101
+
102
+ ### clang-tidy
103
+
104
+ `.clang-tidy` 不写标准,标准来自编译数据库。检查项保持 Google 基线:
105
+
106
+ ```yaml
107
+ Checks: '-*, google-*, readability-identifier-naming'
108
+ WarningsAsErrors: '*'
109
+ FormatStyle: file
110
+ ```
111
+
112
+ 低标准工程不要为了通过检查去打开 `cppcoreguidelines-*` 整包;那会把 C++ Core Guidelines 的现代写法带进 C++11 代码。
113
+
114
+ ### 标准库
115
+
116
+ 默认用系统默认标准库。需要 libc++ 时,在 CMake 工具链文件或 target 选项里显式写:
117
+
118
+ ```cmake
119
+ target_compile_options(app PRIVATE -stdlib=libc++)
120
+ target_link_options(app PRIVATE -stdlib=libc++)
121
+ ```
122
+
123
+ 不要只写进某个人的 `.clangd` 或 shell 脚本;换机器后不可复现。
124
+
125
+ ## 降档时改什么
126
+
127
+ 默认模板按 `__cplusplus` 条件使用 `std::format`;选低标准仍不是只改一个数字:
128
+
129
+ | 从默认 C++23 降到 | 必须处理 |
130
+ | --- | --- |
131
+ | `c++20` | `std::print` → `std::format` + `std::cout`;`std::expected` → `std::optional`/结果类型 |
132
+ | `c++17` | 再去掉 `std::format`,用 `std::ostringstream`;去掉 `std::span`、`std::bit_cast` |
133
+ | `c++14` | 去掉 `std::string_view`、`[[nodiscard]]`、结构化绑定、`if constexpr`、`std::optional` |
134
+ | `c++11` | 再去掉通用 lambda、`std::make_unique`、`std::index_sequence`、`constexpr` 放宽用法 |
135
+
136
+ 每个标准目录里的“不能假设”和“降档要改什么”是该档的检查清单;模板只保证自身能构建,不替项目代码做兼容层。
137
+
138
+ ## 验证矩阵
139
+
140
+ | 标准 | configure | build | run | compile_commands `-std` | clang-format | clangd |
141
+ | --- | --- | --- | --- | --- | --- | --- |
142
+ | `c++11` | 必测 | 必测 | 必测 | `c++11` | `c++11` | 读 DB |
143
+ | `c++14` | 必测 | 必测 | 必测 | `c++14` | `c++14` | 读 DB |
144
+ | `c++17` | 必测 | 必测 | 必测 | `c++17` | `c++17` | 读 DB |
145
+ | `c++20` | 必测 | 必测 | 必测 | `c++20` | `c++20` | 读 DB |
146
+ | `c++23` | 必测 | 必测 | 必测 | `c++23` | `Latest` | 读 DB |
147
+
148
+ 本仓库在 WSL(clang 21.1.8、CMake 4.2.3、Ninja 1.13.2)上跑过四套模板 × 五档共 20 个构建:single、multi、static-library、shared-library 全部 configure/build/CTest 通过,`compile_commands.json` 都得到精确的 `-std=c++11/14/17/20/23`。模板用 `__cplusplus` 条件选择 `std::format` 或字符串拼接,默认仍交付 C++23。可复现脚本:[checking-standard-matrix.sh](../../../../scripts/checking-standard-matrix.sh)。
149
+
150
+ ## 新增标准
151
+
152
+ 增加 C++26 或更高标准时,不复制模板,按这个顺序做:
153
+
154
+ 1. 新建 `standards/c++26/`,写 `README.md`,复制对应档的 `cmake-snippet.cmake` 并改数字。
155
+ 2. 更新本页矩阵和 `checking-environment.mjs` 的 `STANDARDS`。
156
+ 3. 确认 CMake 的 `CXX_STANDARD 26`、clang-format 的 `Standard` 能力、编译器/标准库门槛。
157
+ 4. 在四套模板 × 新档上跑 configure/build/CTest,并在 `compile_commands.json` 核对 `-std=c++26`。
158
+ 5. 只在新档稳定后改默认;默认变更属于发布说明里要写清的破坏性变化。
159
+
160
+ ## 相关文件
161
+
162
+ - [environment.md](../environment.md):四轴声明与校验。
163
+ - [cmake.md](../cmake.md):CMake 形状与排版。
164
+ - [static-analysis.md](../static-analysis.md):clang-format / clang-tidy / clangd 分工。
165
+ - [01-build.md](../../steps/01-build.md):定构建步骤。
@@ -0,0 +1,50 @@
1
+ # C++11 标准档案
2
+
3
+ [返回标准索引](../README.md)
4
+
5
+ | 项 | 值 |
6
+ | --- | --- |
7
+ | `standard` | `c++11` |
8
+ | CMake meta-feature | `cxx_std_11` |
9
+ | `CXX_STANDARD` | `11` |
10
+ | `__cplusplus` | `201103L` |
11
+ | clang-format 21/22 | `Standard: c++11` |
12
+ | 模板实用下限 | GCC 4.8 / Clang 3.4 |
13
+
14
+ ## 最重要的三件事
15
+
16
+ 1. 代码只用 C++11 子集:没有 `std::make_unique`、通用 lambda、`std::string_view`、`std::optional`、`if constexpr`。
17
+ 2. CMake 同时写 `cxx_std_11` 和 `CXX_STANDARD 11`,并开 `CXX_STANDARD_REQUIRED ON`;只写 `cxx_std_11` 可能被更高默认标准满足。
18
+ 3. 验证时读 `compile_commands.json`,确认实际是 `-std=c++11`,不是 `gnu++11` 或更高的 `-std`。
19
+
20
+ ## 本档能用
21
+
22
+ - `auto`、范围 `for`、lambda、右值引用与移动语义。
23
+ - `std::unique_ptr`、`std::shared_ptr`、`std::thread`、`std::chrono`。
24
+ - `enum class`、`override` / `final`、变参模板、`constexpr` 的受限用法。
25
+ - `std::array`、`std::unordered_map` / `unordered_set`。
26
+
27
+ ## 本档不能假设
28
+
29
+ - 没有 `std::make_unique`、泛型 lambda、变量模板、返回类型推导。
30
+ - 没有 `std::string_view`、`std::optional`、`std::variant`、`if constexpr`、结构化绑定。
31
+ - 没有 `[[nodiscard]]`、`std::filesystem`、`std::format`、`std::print`。
32
+ - 不要用 C++14 的放宽 `constexpr` 写循环或多语句函数。
33
+
34
+ ## CMake
35
+
36
+ 把 [cmake-snippet.cmake](cmake-snippet.cmake) 的 target 名换成实际 target。新建工程仍建议 CMake ≥ 3.20;低版本工具链只影响 `CXX_STANDARD` 的可用性,不影响本工作流的目录约定。
37
+
38
+ ## 工具
39
+
40
+ - `.clang-format`:`Standard: c++11`。
41
+ - `.clangd`:不写 `-std`,从 `compile_commands.json` 读。
42
+ - `.clang-tidy`:仍用 Google 基线;不要打开 `cppcoreguidelines-*` 整包。
43
+
44
+ ## 降档/升级
45
+
46
+ 这是最低档,没有“再降”的路径。从 C++14 降到这里时,先去掉 `std::make_unique`、泛型 lambda、返回类型推导和变量模板;`std::unique_ptr<T>(new T(...))` 只作为过渡,不要在新代码里扩散。
47
+
48
+ ## 验证
49
+
50
+ configure、build、run 必测;`compile_commands.json` 的最后一个 `-std=` 必须是 `-std=c++11`,不能是 `gnu++11`。模板的 `__cplusplus` 分支在 C++11 下应走字符串拼接实现。
@@ -0,0 +1,7 @@
1
+ # c++11:把 target 名换成实际 target;与 environment.json 的 standard 一致。
2
+ target_compile_features(app PRIVATE cxx_std_11)
3
+ set_target_properties(app PROPERTIES
4
+ CXX_STANDARD 11
5
+ CXX_STANDARD_REQUIRED ON
6
+ CXX_EXTENSIONS OFF
7
+ )
@@ -0,0 +1,48 @@
1
+ # C++14 标准档案
2
+
3
+ [返回标准索引](../README.md)
4
+
5
+ | 项 | 值 |
6
+ | --- | --- |
7
+ | `standard` | `c++14` |
8
+ | CMake meta-feature | `cxx_std_14` |
9
+ | `CXX_STANDARD` | `14` |
10
+ | `__cplusplus` | `201402L` |
11
+ | clang-format 21/22 | `Standard: c++14` |
12
+ | 模板实用下限 | GCC 5 / Clang 3.4 |
13
+
14
+ ## 最重要的三件事
15
+
16
+ 1. C++14 只多出 `std::make_unique`、泛型 lambda、放宽的 `constexpr` 等;不要顺手用 C++17 的 `string_view`/`optional`。
17
+ 2. `std::make_unique` 是这一档最常用的替换点,但不要把 C++11 的 `std::unique_ptr(new T)` 直接当成跨档写法。
18
+ 3. 同样用 `CXX_STANDARD 14` + `REQUIRED ON` 锁定模式,并检查 `compile_commands.json` 是 `-std=c++14`。
19
+
20
+ ## 本档能用
21
+
22
+ - C++11 的全部内容。
23
+ - `std::make_unique`、泛型 lambda、变量模板、返回类型推导。
24
+ - 二进制字面量、数字分隔符、放宽的 `constexpr`、`std::integer_sequence`。
25
+
26
+ ## 本档不能假设
27
+
28
+ - 没有 `std::string_view`、`std::optional`、`std::variant`、`if constexpr`、结构化绑定。
29
+ - 没有 `[[nodiscard]]`、`std::filesystem`、`std::format`、`std::print`。
30
+ - 不要把结构化绑定或 `if constexpr` 写进 C++14 代码再靠编译器扩展通过。
31
+
32
+ ## CMake
33
+
34
+ 把 [cmake-snippet.cmake](cmake-snippet.cmake) 的 target 名换成实际 target。
35
+
36
+ ## 工具
37
+
38
+ - `.clang-format`:`Standard: c++14`。
39
+ - `.clangd`:不写 `-std`,从 `compile_commands.json` 读。
40
+ - `.clang-tidy`:仍用 Google 基线;命名规则不要引入 C++17 属性。
41
+
42
+ ## 降档/升级
43
+
44
+ 从 C++17 降到这里时,把 `string_view` 改成 `const std::string&`,把 `optional` 改成 `bool` + 输出参数或项目结果类型,把 `if constexpr` 改成标签分派或重载。升级到 C++17 后也不要立刻把公共接口全改成 `string_view`,先看调用方生命周期。
45
+
46
+ ## 验证
47
+
48
+ configure、build、run 必测;`compile_commands.json` 的最后一个 `-std=` 必须是 `-std=c++14`。模板在 C++14 下应走字符串拼接实现。
@@ -0,0 +1,7 @@
1
+ # c++14:把 target 名换成实际 target;与 environment.json 的 standard 一致。
2
+ target_compile_features(app PRIVATE cxx_std_14)
3
+ set_target_properties(app PROPERTIES
4
+ CXX_STANDARD 14
5
+ CXX_STANDARD_REQUIRED ON
6
+ CXX_EXTENSIONS OFF
7
+ )
@@ -0,0 +1,49 @@
1
+ # C++17 标准档案
2
+
3
+ [返回标准索引](../README.md)
4
+
5
+ | 项 | 值 |
6
+ | --- | --- |
7
+ | `standard` | `c++17` |
8
+ | CMake meta-feature | `cxx_std_17` |
9
+ | `CXX_STANDARD` | `17` |
10
+ | `__cplusplus` | `201703L` |
11
+ | clang-format 21/22 | `Standard: c++17` |
12
+ | 模板实用下限 | GCC 7 / Clang 5(语言核心) |
13
+
14
+ ## 最重要的三件事
15
+
16
+ 1. `std::string_view`/`std::optional`/`std::variant`/`if constexpr` 是这一档的主力;它们不能出现在 C++11/14 档案里。
17
+ 2. 还没有 `std::format`;字符串拼接/`ostringstream` 仍是这一档的默认写法。
18
+ 3. `std::filesystem` 在旧 GCC 上要额外链接 `stdc++fs`,先查工具链再写进 CMake。
19
+
20
+ ## 本档能用
21
+
22
+ - C++14 的全部内容。
23
+ - `std::string_view`、`std::optional`、`std::variant`、`std::any`。
24
+ - `if constexpr`、结构化绑定、`[[nodiscard]]`、内联变量、嵌套命名空间。
25
+ - `std::filesystem`、并行算法(库实现和链接方式另看)。
26
+
27
+ ## 本档不能假设
28
+
29
+ - 没有 concepts、ranges、`std::format`、`std::span`、`std::bit_cast`。
30
+ - 没有 `std::print`、`std::expected`、`std::stacktrace`。
31
+ - `std::filesystem` 在 GCC 8 需要额外链接 `stdc++fs`,GCC 9 起才稳定;不要把“语言核心达标”当成文件系统库也达标。
32
+
33
+ ## CMake
34
+
35
+ 把 [cmake-snippet.cmake](cmake-snippet.cmake) 的 target 名换成实际 target。用到 `std::filesystem` 且工具链较老时,在 target 上补 `stdc++fs`,不要全局加链接选项。
36
+
37
+ ## 工具
38
+
39
+ - `.clang-format`:`Standard: c++17`。
40
+ - `.clangd`:不写 `-std`,从 `compile_commands.json` 读。
41
+ - `.clang-tidy`:Google 基线;`[[nodiscard]]` 可以开始用于公共查询。
42
+
43
+ ## 降档/升级
44
+
45
+ 从 C++20 降到这里时,把 concepts 改成 `enable_if`/重载,把 ranges 改成迭代器算法,把 `std::format` 改成 `std::ostringstream`。升级到 C++20 后先确认 `std::format` 的库门槛(libstdc++ 13+ / libc++ 14+),不要只看编译器版本。
46
+
47
+ ## 验证
48
+
49
+ configure、build、run 必测;`compile_commands.json` 的最后一个 `-std=` 必须是 `-std=c++17`。模板在 C++17 下仍走字符串拼接实现。
@@ -0,0 +1,7 @@
1
+ # c++17:把 target 名换成实际 target;与 environment.json 的 standard 一致。
2
+ target_compile_features(app PRIVATE cxx_std_17)
3
+ set_target_properties(app PROPERTIES
4
+ CXX_STANDARD 17
5
+ CXX_STANDARD_REQUIRED ON
6
+ CXX_EXTENSIONS OFF
7
+ )
@@ -0,0 +1,49 @@
1
+ # C++20 标准档案
2
+
3
+ [返回标准索引](../README.md)
4
+
5
+ | 项 | 值 |
6
+ | --- | --- |
7
+ | `standard` | `c++20` |
8
+ | CMake meta-feature | `cxx_std_20` |
9
+ | `CXX_STANDARD` | `20` |
10
+ | `__cplusplus` | `202002L` |
11
+ | clang-format 21/22 | `Standard: c++20` |
12
+ | 模板实用下限 | GCC 13 / Clang 16(`std::format`) |
13
+
14
+ ## 最重要的三件事
15
+
16
+ 1. `std::format` 是这一档的库门槛:libstdc++ 13+,libc++ 14+(特性宏到 19 才稳定),不是有 `-std=c++20` 就自动可用。
17
+ 2. concepts/ranges/`std::span`/`std::bit_cast` 可以用;`std::print`、`std::expected`、`if consteval` 仍不能假设。
18
+ 3. 模板在 `__cplusplus >= 202002L` 时切到 `std::format`;降回 C++17 时必须把它换回 `std::ostringstream`。
19
+
20
+ ## 本档能用
21
+
22
+ - C++17 的全部内容。
23
+ - concepts、requires、ranges、`std::span`、`std::bit_cast`、`std::source_location`。
24
+ - `std::format`、协程、`std::jthread`、三路比较。
25
+ - 模块语法(工具链支持不完整,模板不使用)。
26
+
27
+ ## 本档不能假设
28
+
29
+ - 没有 `std::print`、`std::expected`、`std::stacktrace`、`if consteval`、显式对象参数。
30
+ - `std::format` 不只看语言核心:libstdc++ 13+;libc++ 14+ 实现完成,但特性宏到 19 才稳定。
31
+ - 模块、协程的构建支持因编译器/构建系统而异;模板不依赖它们。
32
+
33
+ ## CMake
34
+
35
+ 把 [cmake-snippet.cmake](cmake-snippet.cmake) 的 target 名换成实际 target。模板从这一档开始会在 `__cplusplus >= 202002L` 时使用 `std::format`,此前用字符串拼接。
36
+
37
+ ## 工具
38
+
39
+ - `.clang-format`:`Standard: c++20`。
40
+ - `.clangd`:不写 `-std`,从 `compile_commands.json` 读。
41
+ - `.clang-tidy`:Google 基线;不要为了 concepts 打开一整族非 Google 检查。
42
+
43
+ ## 降档/升级
44
+
45
+ 从 C++23 降到这里时,把 `std::print` 改成 `std::format` + `std::cout`,把 `std::expected` 改成 `std::optional` 或项目结果类型,去掉 `if consteval`。升级到 C++23 后仍要逐项确认库实现,不要因为 `-std=c++23` 通过就假定 `print`/`stacktrace` 可用。
46
+
47
+ ## 验证
48
+
49
+ configure、build、run 必测;`compile_commands.json` 的最后一个 `-std=` 必须是 `-std=c++20`。模板在 C++20 下应走 `std::format` 分支。
@@ -0,0 +1,7 @@
1
+ # c++20:把 target 名换成实际 target;与 environment.json 的 standard 一致。
2
+ target_compile_features(app PRIVATE cxx_std_20)
3
+ set_target_properties(app PROPERTIES
4
+ CXX_STANDARD 20
5
+ CXX_STANDARD_REQUIRED ON
6
+ CXX_EXTENSIONS OFF
7
+ )
@@ -0,0 +1,50 @@
1
+ # C++23 标准档案
2
+
3
+ [返回标准索引](../README.md)
4
+
5
+ | 项 | 值 |
6
+ | --- | --- |
7
+ | `standard` | `c++23` |
8
+ | CMake meta-feature | `cxx_std_23` |
9
+ | `CXX_STANDARD` | `23` |
10
+ | `__cplusplus` | `202302L` |
11
+ | clang-format 21/22 | `Standard: Latest` |
12
+ | 模板实用下限 | GCC 13 / Clang 17(模板只用 `std::format`) |
13
+
14
+ ## 最重要的三件事
15
+
16
+ 1. C++23 在 GCC/Clang 上仍是 Partial;`std::print` 要 libstdc++ 14+/libc++ 19+,`std::stacktrace` 还要链接库。
17
+ 2. clang-format 21/22 不认识 `c++23`,配置写 `Standard: Latest`;`.clangd` 不写 `-std`,否则会把编译数据库降回 C++20。
18
+ 3. 模板默认 23,但模板只强依赖 `std::format`;不要因为默认 23 就在公共头里用 `std::expected`/`std::print`,先确认所有 target 和库门槛。
19
+
20
+ ## 本档能用
21
+
22
+ - C++20 的全部内容。
23
+ - `std::print` / `std::println`、`std::expected`、`std::stacktrace`。
24
+ - `if consteval`、显式对象参数(deducing this)、`std::mdspan`、`std::flat_map`。
25
+ - ranges 的 C++23 增补(工具链实现为准)。
26
+
27
+ ## 本档不能假设
28
+
29
+ - C++23 在 GCC/Clang 上仍是 Partial:具体设施要查编译器状态页,不能只看 `-std=c++23`。
30
+ - `std::print` 的库门槛是 libstdc++ 14+ / libc++ 19+;`std::stacktrace` 还要链接对应库,链接失败不是语法错误。
31
+ - `std::expected` 的 monadic 接口、`std::flat_map` 等设施在旧标准库上可能缺失。
32
+ - 模板只用 `std::format`,不会因为默认 C++23 就强依赖 `print`/`stacktrace`。
33
+
34
+ ## CMake
35
+
36
+ 把 [cmake-snippet.cmake](cmake-snippet.cmake) 的 target 名换成实际 target。默认模板的 `cxx_std_23` 和 `CXX_STANDARD 23` 必须与 `environment.json` 的 `standard` 一致。
37
+
38
+ ## 工具
39
+
40
+ - `.clang-format`:`Standard: Latest`(21/22 不接受 `c++23`;`Latest` 按工具支持的最高标准解析)。
41
+ - `.clangd`:不写 `-std`,从 `compile_commands.json` 读;写死 `-std=c++20` 会让 `<print>` 和 `if consteval` 解析失败。
42
+ - `.clang-tidy`:Google 基线;不要因为 C++23 就打开 `cppcoreguidelines-*` 整包。
43
+
44
+ ## 降档/升级
45
+
46
+ 从 C++23 降到 C++20 见 [C++20 档案](../c++20/README.md)。升级到 C++26 前先确认 CMake 3.25+、编译器/标准库支持、clang-format 的 `c++26` 枚举;新增目录流程见[标准索引](../README.md#新增标准)。
47
+
48
+ ## 验证
49
+
50
+ configure、build、run 必测;`compile_commands.json` 的最后一个 `-std=` 必须是 `-std=c++23`。模板在 C++23 下走 `std::format` 分支;若使用 `print`/`stacktrace`,另做链接测试。
@@ -0,0 +1,7 @@
1
+ # c++23:把 target 名换成实际 target;与 environment.json 的 standard 一致。
2
+ target_compile_features(app PRIVATE cxx_std_23)
3
+ set_target_properties(app PROPERTIES
4
+ CXX_STANDARD 23
5
+ CXX_STANDARD_REQUIRED ON
6
+ CXX_EXTENSIONS OFF
7
+ )