mcpField
C
cpp-systems

cpp-systems

github.com/iliaal开发4565 次安装3 天前更新
代码仓库

关于 cpp-systems

面向 C++ 系统与库开发和审查的技能,以 C++17 为基线,并在适用处说明 C++20 特性。重点包括明确资源所有权、兼容性、遵循仓库约定,以及通过构建、分析和测试进行验证。

主要功能

  1. 01RAII 与所有权指引
  2. 02C++17 基线及 C++20 说明
  3. 03API 与 ABI 兼容实践
  4. 04仓库约定与工具链
  5. 05构建、分析及消毒器检查

适用场景

  1. 01实现 C++ 库变更
  2. 02审查资源生命周期与所有权
  3. 03维护公共 API 和 ABI
  4. 04验证构建与多线程代码

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/iliaal/ai-skills --skill cpp-systems

安装后在 Claude Code 中输入/cpp-systems确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

SPEC.md
references/
api-and-abi.md
cmake-and-tooling.md
concurrency-and-verification.md
legibility-standard.md
value-and-interface-design.md

详细介绍

C++ 系统与库

以 C++17 为基线,并在项目标准允许时注明 C++20 特性。对于纯 C(手动管理生命周期、状态枚举、原生扩展),请参阅 ia-c-systems 技能。

工作规则

  • 明确资源所有权,并使用 RAII 确保所有退出路径都会释放资源。
  • 借用视图的生命周期不得超出其后备存储,并在特殊成员发生变化时检查复制和移动行为。
  • 遵循项目的错误处理模型和支持的语言标准。
  • 保持 ABI 稳定,避免在持有锁或可能失效的容器迭代器时调用未知回调。

仓库约定优先于本技能

编写代码前,检查 CMakeLists.txt 中的 CXX_STANDARD,阅读 .clang-format 和 .clang-tidy,并阅读相邻的两个翻译单元。若它们与以下规则冲突,以仓库约定为准。

实际可能遇到的冲突:

本地约束结果
-fno-exceptions错误处理使用错误码或类似 expected 的类型。构造函数无法报告可恢复的失败,因此应使用可失败的工厂函数,或构造有效的回退状态。仅当项目的 OOM 策略要求观察空指针并进行恢复时,才使用 new (std::nothrow);若策略是终止程序,则使用普通 new 即可
标准固定在 C++17 以下不可使用 std::optional、string_view、结构化绑定或 if constexpr;使用前请先确认
公共头文件要求 ABI 稳定不得更改布局、修改内联函数或添加虚函数:请加载 ABI 参考资料
嵌入式或 freestanding 目标不使用 RTTI,热路径中不进行动态分配,也可能不使用 STL 容器

所有权与 RAII

每项资源都恰有一个所有者,且该所有者是一个会在析构时释放资源的对象。在应用程序代码中直接使用 new 或 delete 属于缺陷。

  • 独占所有权使用 std::unique_ptr<T>。它是默认选择;与裸指针相比,开销为零。
  • 仅当生命周期确实由多个对象共享,且无法表达为“所有者的生命周期长于使用者”时,才使用 std::shared_ptr<T>。优先级应排在第三,而非第一。
  • 使用 std::weak_ptr<T> 打破所有权循环。LeakSanitizer 会报告从任何根都无法到达的循环,但不会报告仍可从全局变量或其他已注册根到达的循环;检测结果也因平台和配置而异。不要依赖 Sanitizer 来发现这些问题。
  • 裸 T* 和 T& 表示非拥有式观察,用于此角色是正确的。按值接收 unique_ptr 的参数表示将接管所有权;接收 T* 的参数则表示不会接管。
  • 在新的公共 API 中,借用连续范围使用 std::span<T>(C++20)或“指针加长度”的组合,因为在此处使用 const std::vector<T>& 会排除其他所有容器。若基线为 C++17,或内部代码的调用方本来就都持有 vector,则使用 const std::vector<T>& 没问题,也更简单。

零法则:不拥有任何资源的类不声明析构函数、复制操作或移动操作。组合能够自行管理资源的成员,即可免费正确获得全部五个特殊成员。五法则:只要声明了析构函数、复制构造函数、复制赋值运算符、移动构造函数或移动赋值运算符中的任意一个,作者就必须考虑全部五个。用户声明析构函数会抑制隐式移动操作,因此新增析构函数的类可能会悄然从原先的移动转为深拷贝。

规范

  • 除非明确要求破坏兼容性,否则保持行为和 API 兼容。修改公共头文件是一个需要做出的决定,不是清理工作。
  • 不要为了单个调用点引入模板、继承体系或策略参数。
  • 文件使用什么就 #include 什么;不要依赖其他头文件的传递性包含。
  • 不要在头文件的命名空间作用域使用 using namespace。应使用完全限定名称,或将 using 限定在函数体内。
  • 如果约束迫使你偏离规范,请在偏离处添加注释并说明该约束。

验证

  • 使用 -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Werror 构建无警告
  • clang-tidy 对差异部分不报告新的问题
  • 在 -fsanitize=address,undefined 下运行测试,且无任何报告
  • 本次更改涉及的任何多线程代码都应在 TSan 下测试,且无任何报告;上述警告选项组合无法检测锁误用
  • clang-format --dry-run --Werror 不产生差异
  • 不新增裸 new/delete;在 unique_ptr 足够时,不新增 shared_ptr
  • 为其新增析构函数的任何类,都应检查其移动操作

特定任务参考

实现或审查相应行为前,请阅读相关参考文档:

适用时,请查阅以下现有专项参考文档:

评论

支持 Markdown