ss-cpp-modern

GitHub

提供 Serial Studio 项目中现代 C++20 编码指导,涵盖智能指针、RAII、概念约束及原子操作等惯用法。用于编写或重构非平凡 C++ 代码时选择正确设计模式,不处理构建或测试。

.claude/skills/ss-cpp-modern/SKILL.md Serial-Studio/Serial-Studio

Trigger Scenarios

编写新的 C++ 类或函数 重构现有 C++ 代码以符合现代风格 决定使用哪种智能指针或 RAII 包装器

Install

npx skills add Serial-Studio/Serial-Studio --skill ss-cpp-modern -g -y
More Options

Non-standard path

npx skills add https://github.com/Serial-Studio/Serial-Studio/tree/master/.claude/skills/ss-cpp-modern -g -y

Use without installing

npx skills use Serial-Studio/Serial-Studio@ss-cpp-modern

指定 Agent (Claude Code)

npx skills add Serial-Studio/Serial-Studio --skill ss-cpp-modern -a claude-code -g -y

安装 repo 全部 skill

npx skills add Serial-Studio/Serial-Studio --all -g -y

预览 repo 内 skill

npx skills add Serial-Studio/Serial-Studio --list

SKILL.md

Frontmatter
{
    "name": "ss-cpp-modern",
    "description": "Modern C++20 authoring guidance for Serial Studio (Qt 6.11, C++20): concepts, ranges, move\/RAII, std smart pointers, constexpr, lock-free SPSC atomics. Use when writing or refactoring non-trivial C++ here and you want the idiomatic modern-C++ shape — picking a smart pointer, designing an RAII wrapper, a concept-constrained template, or a hotpath data structure. Defers all style\/build\/sanitize\/test rules to CLAUDE.md, scripts\/, and the ss-hotpath \/ ss-verify \/ qt-cpp-review skills — it does NOT build, sanitize, or run anything."
}

Serial Studio — modern C++20 authoring

Adapted from jeffallan's cpp-pro skill, trimmed to what this repo actually uses and realigned to its rules. This is authoring guidance — the idiomatic C++20 shape of a thing. It does not own style, build, or verification:

  • Style / formatting / structure: scripts/code-verify.py is the contract. See [[ss-verify]]. Don't re-derive its rules; run it. (100-col, 2-space, LF, m_/s_/k naming, header member order, Q_EMIT, no in-header init, [[nodiscard]], ASCII-only.)
  • Hotpath / threading / Power of Ten: see [[ss-hotpath]] before touching the data path.
  • Correctness review: see [[qt-cpp-review]] after writing.
  • Building / sanitizers / running: you don't. The developer builds the Pro edition and runs sanitizers (scripts/) themselves. Never invoke cmake/jom/clang/the compiler.

House baselines (this repo, not generic C++)

These override the generic "C++ Pro" advice you may know:

  • std smart pointers, not Qt ones. std::unique_ptr / std::shared_ptr / std::weak_ptr are house style (e.g. TimestampedFramePtr = std::shared_ptr<TimestampedFrame>). Do not reach for QScopedPointer / QSharedPointer.
  • No raw new/delete outside a QObject parent-owned tree or a documented RAII wrapper. QObject children are parent-owned; everything else is a smart pointer or a value.
  • static_cast and friends, never C-style casts. No reinterpret_cast/dynamic_cast on the hotpath (Power of Ten).
  • auto with judgement, not reflexively. Use it when the type is obvious from the initializer (auto it = map.find(...)); spell the type out when it aids the reader. The repo favors readable concrete types in signatures.
  • Const-correct always. [[nodiscard]] on every non-void return in a header (linter enforces). Methods that don't mutate are const.
  • Exceptions vs error codes: Lua/JS host boundaries force unwind tables + try/catch + lua_atpanic (see the Lua exception-safety setup); elsewhere prefer status returns / std::optional / signals consistently within a subsystem (ERR-12). Don't mix patterns in one class.

When to reach for what

Before writing a type that owns anything, state its ownership story in one chat sentence ("X solely owns the handle; the worker observes via weak_ptr") — the shape follows from the story, and a story you can't state in one sentence is a design smell (doc/claude/j-space.md, verbalize-to-load).

Smart pointer choice

  • std::unique_ptr<T> — sole ownership; the default. const std::unique_ptr<T> for a member that is created once and lives for the owner's lifetime (scoped, non-reseatable).
  • std::shared_ptr<T> — genuine shared ownership only (e.g. a frame handed to several async sinks). On the dashboard hotpath, blocks come from the pooled slots (DataModel::BlockStager on the frame lane, StreamProcessor::claimBlockSlot() on the stream lane; slot pool), not fresh make_shared — see [[ss-hotpath]] SS-HOT-3.
  • std::weak_ptr<T> — break a shared cycle / observe without owning.
  • A QObject with a parent — parent-owned; no smart pointer needed (and don't add one).

Concepts (C++20) over SFINAE

Constrain templates with a named concept instead of std::enable_if. A concept reads as a self-documenting requirement and gives better diagnostics. Prefer requires-clauses on overloaded templates; reserve static_assert for hard mandates that should never be a silent overload-resolution miss. Keep concept names domain-specific.

Ranges / views (C++20)

Lazy std::views::filter | transform | take pipelines replace hand-rolled loops for transformation chains — but they are off the hotpath by default. The frame extractors and per-dataset transforms are hand-tuned, fixed-bound loops (Power of Ten SS-POT-2); do not introduce range pipelines there without benchmarking (--benchmark-hotpath).

Move semantics & RAII

  • Define the special members deliberately: a type owning a resource is either Q_DISABLE_COPY
    • movable (move-and-swap assignment) or a value type with the rule of zero. Document the moved-from state.
  • return std::move(local) defeats NRVO — return the named local directly. A const local also blocks the implicit move on return.
  • RAII wrap every raw OS/library handle (file, socket, libusb/hidapi handle) so cleanup is exception-safe and ordering is explicit. The driver destructors here are order-sensitive (join the worker thread before tearing down the resource it touches — SS-DRV-1).

constexpr / compile-time

Prefer constexpr (and kCamelCase constants) over macros and runtime initialization for fixed data. Don't use a dynamically-sized container for statically-sized data (VAR-4) — use std::array.

Lock-free / atomics (the SPSC ring)

CircularBuffer + FrameReader are a single-producer/single-consumer, main-thread design — no mutex (SS-HOT-1). When you genuinely need cross-thread coordination elsewhere, use std::atomic with explicit memory ordering (acquire/release to publish-then-observe), not ad-hoc volatile or relaxed-everywhere. Shared counters across threads are std::atomic or mutex-guarded (THR-5). The JS watchdog's interrupt flag is the canonical atomic-flag pattern.

Reference

  • references/cpp20-idioms.md — concept, ranges, move, RAII, and atomic snippets written in this repo's naming/style (not the generic upstream examples).

Output expectations

When you implement, follow CLAUDE.md's handoff rules: one-line statement of intent before non-trivial work, a one/two-sentence summary of what changed when you stop, no doc files unless asked. Provide the header + implementation edits; mention CMake list additions in chat if a new translation unit is needed (the developer wires and builds it). Do not paste whole-file rewrites — targeted edits only.

Version History

  • 44c9452 Current 2026-09-22 22:28

    更新核心模块分层规范,明确跨库通信需通过 typed Core::Bus::MessageBus 或根绑定接口,禁止直接实例引用;细化共享叶子代码归属及单元测试链接方式。

  • 615dff9 2026-08-28 20:00
  • cb2f5d2 2026-08-20 08:59

Same Skill Collection

.claude/skills/qt-cpp-review/SKILL.md
.claude/skills/qt-qml-review/SKILL.md
.claude/skills/ss-ai-audit/SKILL.md
.claude/skills/ss-hotpath/SKILL.md
.claude/skills/ss-implement/SKILL.md
.claude/skills/ss-log-mistake/SKILL.md
.claude/skills/ss-new-driver/SKILL.md
.claude/skills/ss-plan/SKILL.md
.claude/skills/ss-spec/SKILL.md
.claude/skills/ss-tasks/SKILL.md
.claude/skills/ss-verify/SKILL.md
.claude/skills/cpp-compiler-flags/SKILL.md
.claude/skills/qt-qml/SKILL.md
.claude/skills/ss-docs/SKILL.md

Metadata

Files
0
Version
89a23c2
Hash
11f16a24
Indexed
2026-08-20 08:59

Accueil - Wiki
Copyright © 2011-2026 iteam. Current version is 2.155.2. UTC+08:00, 2026-11-02 01:56
浙ICP备14020137号-1