Cpp coding
Skill nguyenthdat/opencode-manager/registry/skills/cpp-coding
Comprehensive idiomatic modern C++ guidance: 176 prioritized rules across 15 categories covering RAII, smart pointers, memory safety, templates, concurrency, and performance. Use when writing, reviewing, refactoring, or optimizing C++ (`.cpp`, `.cc`, `.cxx`, `.hpp`, `.h`, `.hh`, `CMakeLists.txt`). Targets C++17/20/23; prefer the project's declared standard version and only apply concepts/ranges/coroutines/modules/`std::expected` when the project's compiler and `CMAKE_CXX_STANDARD` actually support them.From its SKILL.md
npx -y skills add nguyenthdat/opencode-manager --skill cpp-codingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
28.5 KB, ~7.5k tokens by cl100k_base, as published. Nobody here has run it
C++ Best Practices
Comprehensive guide for writing high-quality, idiomatic modern C++. Contains 176 rules across 15 categories, prioritized by impact. Project constraints override generic defaults: preserve the declared CMAKE_CXX_STANDARD/-std= flag, compiler support matrix, and existing memory-management conventions unless the user explicitly requests a modernization pass.
This skill is for idiomatic modern C++ — RAII, smart pointers, templates, the STL, exceptions/std::expected. For plain C code (manual memory management, no classes/templates/exceptions, C ABI), use the sibling c-coding skill instead. Do not apply C++-only idioms (RAII, unique_ptr, templates, exceptions) to a .c file, and do not apply C-style manual memory management to idiomatic C++.
When to Apply
Reference these guidelines when:
- Writing new C++ classes, functions, or headers
- Choosing between
unique_ptr,shared_ptr, raw pointers, and references - Implementing error handling (exceptions,
std::expected, error codes) - Designing public APIs for a library or shared object
- Reviewing code for ownership, lifetime, or memory-safety issues
- Writing template or generic code, or migrating SFINAE to concepts
- Writing or reviewing concurrent code (threads, atomics, coroutines)
- Optimizing hot paths or reducing allocations
- Setting up
CMakeLists.txt,.clang-tidy, or CI sanitizer builds
Modern C++ (C++17 / C++20 / C++23)
Preserve the project's declared standard (CMAKE_CXX_STANDARD, -std=c++XX) and compiler baseline unless migration is explicitly in scope. For new projects, prefer at minimum C++17 for structured bindings and if constexpr, and C++20 where the toolchain (GCC 10+, Clang 14+, MSVC 19.29+) reliably supports it.
C++17 — genuinely current baseline:
- Structured bindings (
auto [it, ok] = map.insert(...)) instead of.first/.second if constexprfor compile-time branching without SFINAE tricksstd::optional<T>,std::variant<T...>,std::anyfor absence/sum-types/type-erasurestd::string_viewfor non-owning string parameters- Class template argument deduction (CTAD) —
std::vector v{1, 2, 3};needs no<int> std::filesystemfor portable path/file operations[[nodiscard]],[[maybe_unused]],[[fallthrough]]attributes
C++20 — adopt where the toolchain supports it:
- Concepts (
std::integral,std::invocable, user-definedrequiresclauses) instead ofenable_if/SFINAE - Ranges (
std::ranges::sort, views, pipe composition) instead of iterator-pair algorithms - Coroutines (
co_await/co_yield/co_return) for structured async code std::span<T>for bounds-aware, non-owning views over contiguous datastd::jthread(auto-joining, cooperatively cancellable thread)- Modules (
import/export module) — adopt only after confirming build-system maturity (CMake 3.28+, compiler support); header/#includeremains the safe default otherwise - Three-way comparison (
operator<=>) to replace hand-written relational operator sets - Designated initializers,
std::atomic_ref,std::format(or{fmt}as the pre-standard equivalent)
C++23 — use only when the project's toolchain is confirmed current enough:
std::expected<T, E>for explicit, allocation-free error returns as an alternative to exceptions- Deducing
this(explicit object parameters) to de-duplicate const/non-const and ref-qualified overloads std::mdspanfor multi-dimensional array viewsif constevalfor compile-time-vs-runtime branchingstd::ranges::tofor materializing ranges into containers
For the authoritative, evolving detail, consult the C++ Core Guidelines and cppreference.com's per-standard feature pages. Everything below applies across C++17/20/23; prefer the newer forms above where the project's standard version allows.
Rule Categories by Priority
| Priority | Category | Impact | Prefix | Rules |
|---|---|---|---|---|
| 1 | RAII & Resource Management | CRITICAL | raii- | 12 |
| 2 | Smart Pointers & Ownership | CRITICAL | own- | 13 |
| 3 | Memory Safety | CRITICAL | mem- | 14 |
| 4 | Error Handling | CRITICAL | err- | 13 |
| 5 | Templates & Generic Programming | HIGH | tmpl- | 12 |
| 6 | API Design | HIGH | api- | 14 |
| 7 | Concurrency | HIGH | conc- | 14 |
| 8 | Naming Conventions | MEDIUM | name- | 10 |
| 9 | Type Safety | MEDIUM | type- | 11 |
| 10 | Testing | MEDIUM | test- | 10 |
| 11 | Documentation | MEDIUM | doc- | 8 |
| 12 | Performance Patterns | MEDIUM | perf- | 12 |
| 13 | Project Structure | LOW | proj- | 9 |
| 14 | Linting & Static Analysis | LOW | lint- | 9 |
| 15 | Anti-patterns | REFERENCE | anti- | 15 |
Quick Reference
1. RAII & Resource Management (CRITICAL)
raii-scope-bound-resources- Bind every resource to a scope-owning objectraii-rule-of-zero- Prefer Rule of Zero; let members manage their own resourcesraii-rule-of-five- Implement all five special members together, or noneraii-unique-ptr-default- Default tounique_ptrfor sole ownershipraii-custom-deleter- Use custom deleters for non-memory resourcesraii-lock-guard- Uselock_guard/scoped_lock, never manual lock/unlockraii-scope-exit- Use RAII scope guards instead of goto-cleanupraii-no-manual-new-delete- Never pair manualnew/delete; wrap in an ownerraii-exception-safety-dtor- Destructors must not throw; marknoexceptraii-avoid-two-phase-init- Avoid two-phase init; fully construct in the constructorraii-raii-for-transactions- Use RAII for transactional commit/rollbackraii-file-handle-wrap- Wrap OS/file handles in RAII types
2. Smart Pointers & Ownership (CRITICAL)
own-unique-ptr-sole-unique_ptrfor sole, transferable ownershipown-shared-ptr-shared-shared_ptronly for genuine shared ownershipown-weak-ptr-break-cycles-weak_ptrto breakshared_ptrcyclesown-make-unique-shared- Usemake_unique/make_sharedover rawnewown-raw-pointer-non-owning- Raw pointer/reference means non-owningown-span-view- Usestd::span/string_viewfor non-owning viewsown-pass-by-value-sink- Take ownership by value (unique_ptr) when sinkingown-observer-ptr-reference- Prefer reference over pointer when null is invalidown-shared-ptr-not-default- Don't default toshared_ptr"just in case"own-enable-shared-from-this- Useenable_shared_from_thiscorrectlyown-const-correctness-ownership- Distinguish ownership from access viaconstown-move-transfer- Usestd::moveto transfer ownership explicitlyown-avoid-get-raw-escape- Don't let.get()pointers outlive their owner
3. Memory Safety (CRITICAL)
mem-span-bounds- Usestd::spaninstead of pointer+length pairsmem-string-view-borrow- Usestd::string_viewfor read-only string paramsmem-array-over-c-array- Usestd::arrayinstead of raw C arraysmem-vector-over-manual- Usestd::vectorinstead of manual dynamic arraysmem-at-vs-brackets- Use.at()at boundaries,operator[]in verified hot pathsmem-no-dangling-reference- Never return references/pointers to localsmem-iterator-invalidation- Know which operations invalidate iteratorsmem-use-after-move- Don't use an object afterstd::moveexcept to reassignmem-avoid-c-style-arrays-decay- Avoid array-to-pointer decay in interfacesmem-sanitizer-required- Run ASan/UBSan in test builds, not just releasemem-no-manual-index-arithmetic- Avoid manual pointer/index arithmeticmem-null-check-before-deref- Check pointer validity before dereferencemem-lifetime-of-callback-captures- Don't let lambda captures danglemem-string-lifetime-c-str- Don't retainc_str()/data()past source lifetime
4. Error Handling (CRITICAL)
err-exceptions-vs-expected- Choose exceptions vsstd::expected/error codeserr-raii-exception-safety- Rely on RAII for exception-safe cleanuperr-strong-exception-guarantee- Provide at least the basic guaranteeerr-noexcept-correctness- Mark move operationsnoexcepterr-no-exceptions-across-abi- Don't let exceptions crossextern "C"err-expected-for-recoverable- Usestd::expected<T,E>for recoverable failureserr-optional-for-absence- Usestd::optional<T>for absence, not errorserr-catch-by-const-ref- Catch exceptions byconst&, not by valueerr-no-catch-all-swallow- Don't swallow exceptions with emptycatch(...)err-custom-exception-hierarchy- Derive custom exceptions fromstd::exceptionerr-nodiscard-fallible- Mark fallible functions[[nodiscard]]err-error-context-preserve- Preserve original cause when wrapping errorserr-assert-vs-exception-assert()for programmer errors, exceptions for runtime errors
5. Templates & Generic Programming (HIGH)
tmpl-concepts-over-sfinae- Use C++20 concepts instead of SFINAEtmpl-if-constexpr-branch- Useif constexprfor compile-time branchingtmpl-requires-clause- Userequiresclauses to constrain templates preciselytmpl-avoid-bloat- Minimize template instantiation bloattmpl-crtp-static-polymorphism- Use CRTP for static polymorphismtmpl-variadic-parameter-pack- Use variadic templates and fold expressionstmpl-auto-template-param- Use abbreviated function templates for simple genericstmpl-concept-standard-library- Prefer standard concepts over ad hoc traitstmpl-explicit-instantiation- Use explicit instantiation to control compile timetmpl-type-traits-standard- Use<type_traits>instead of hand-rolled checkstmpl-template-template-param- Use template template parameters judiciouslytmpl-constexpr-function- Preferconstexprfunctions over metaprogramming
6. API Design (HIGH)
api-rule-of-zero-value-types- Value types: rule of zeroapi-const-correctness- Mark methods/parametersconstwherever possibleapi-pass-by-value-sink-ref-view- Decision table for parameter passingapi-nodiscard-return- Annotate[[nodiscard]]on must-check returnsapi-pimpl-abi-stability- Use PIMPL for ABI-stable shared librariesapi-avoid-stl-across-abi- Don't expose STL containers across unstable ABIapi-explicit-constructors- Mark single-argument constructorsexplicitapi-return-value-not-out-param- Return values instead of out-parametersapi-interface-segregation- Keep interfaces small and focusedapi-default-member-init- Use default member initializersapi-strong-types-over-bool- Useenum classinstead of multiple boolsapi-consistent-overload-set- Keep overload sets consistent and unambiguousapi-header-only-inline- Mark header-only free functionsinlineapi-deprecated-attribute- Use[[deprecated]]before removing API
7. Concurrency (HIGH)
conc-jthread-over-thread- Preferstd::jthreadoverstd::threadconc-lock-guard-raii- Always guard mutexes with RAII lock typesconc-avoid-data-races- Guard every piece of shared mutable stateconc-atomic-for-simple-state- Usestd::atomicfor simple counters/flagsconc-lock-ordering-deadlock- Establish lock ordering or usescoped_lockconc-condition-variable-predicate- Always guardwaitwith a predicateconc-async-future-tasks- Usestd::async/std::futurefor simple parallelismconc-coroutines-async-io- Use C++20 coroutines for structured async I/Oconc-thread-pool-over-raw-threads- Use a thread pool, not raw threads per taskconc-shared-mutex-readers- Usestd::shared_mutexwhen reads dominateconc-avoid-detach- Avoidstd::thread::detach()conc-immutable-sharing- Prefer sharing immutable data over synchronizing mutable dataconc-thread-local-storage- Usethread_localfor per-thread stateconc-memory-order-relaxed-care- Default toseq_cst; justify weaker orders
8. Naming Conventions (MEDIUM)
name-types-pascal-PascalCasefor types, classes, enums, conceptsname-functions-lower-snake-lower_snake_casefor functions and variablesname-member-trailing-underscore- Trailing underscore for private membersname-constants-kcamel-or-caps- One consistent constant convention project-widename-macros-all-caps-ALL_CAPSonly for macrosname-namespace-lower-snake- Shortlower_snake_casenamespacesname-template-param-single-letter- Single-letter or PascalCase template paramsname-boolean-is-has- Prefix booleans withis_/has_/can_name-file-name-match-class- Match file name to primary type namename-avoid-hungarian- Avoid Hungarian notation in modern C++
9. Type Safety (MEDIUM)
type-enum-class-over-enum- Useenum classinstead of unscopedenumtype-strong-typedef-ids- Wrap raw ids/handles in strong typestype-optional-nullable- Usestd::optional<T>instead of sentinel valuestype-variant-over-union- Usestd::variantinstead of raw unionstype-avoid-c-style-cast- Use named casts, never C-style caststype-dynamic-cast-polymorphic- Usedynamic_cast/visitor over manual type tagstype-narrowing-conversion-explicit- Make narrowing conversions explicittype-auto-when-clear- Useautowhen the type is obvious or noisytype-structured-bindings- Use structured bindings to unpack aggregatestype-any-for-heterogeneous- Usestd::anysparingly, only for real type erasuretype-strongly-typed-units- Use strongly-typed units instead of raw numerics
10. Testing (MEDIUM)
test-gtest-fixtures- Use GoogleTest fixtures (TEST_F) for shared setuptest-catch2-sections- Use Catch2SECTIONfor given/when/then teststest-gmock-interfaces- Design mockable interfaces for gMocktest-arrange-act-assert- Structure tests as arrange/act/asserttest-sanitizer-ci- Run sanitizer builds as part of the test suitetest-fuzz-entrypoints- Provide libFuzzer entry points for parserstest-death-test-invariants- Use death tests to verify invariant enforcementtest-parameterized-tests- Use parameterized tests instead of copy-pasted casestest-no-shared-mutable-fixture- Avoid shared mutable state between teststest-mock-time- Inject a Clock abstraction for time-dependent code
11. Documentation (MEDIUM)
doc-doxygen-public-api- Document all public API with Doxygen commentsdoc-brief-detailed-tags- Use\brief/\param/\return/\throwsconsistentlydoc-ownership-contract- Document ownership/lifetime for pointer parametersdoc-thread-safety-contract- Document thread-safety guaranteesdoc-header-comment-invariants- Document class invariants near the declarationdoc-example-usage- Provide a minimal usage example for non-trivial APIsdoc-deprecated-migration- Document migration path for[[deprecated]]APIdoc-generated-docs-ci- Build Doxygen docs in CI to catch broken references
12. Performance Patterns (MEDIUM)
perf-move-semantics- Usestd::moveto avoid unnecessary copiesperf-emplace-over-push- Useemplace_backoverpush_back(T(...))perf-reserve-known-size- Callreserve()when final size is knownperf-pass-by-const-ref-large- Pass large objects byconst&perf-avoid-virtual-hot-path- Avoid virtual dispatch in hot inner loopsperf-return-value-optimization- Rely on RVO/NRVO; return by valueperf-avoid-shared-ptr-atomic-overhead- Avoidshared_ptratomics in hot pathsperf-cache-friendly-soa- Prefer structure-of-arrays for cache-friendly loopsperf-avoid-unneeded-allocation- Avoid unnecessary heap allocation in loopsperf-string-concatenation- Avoid repeated string concatenationperf-algorithm-over-handwritten-loop- Prefer<algorithm>/<ranges>over hand-written loopsperf-profile-before-optimize- Profile before micro-optimizing
13. Project Structure (LOW)
proj-header-source-split- Split declarations from definitionsproj-include-guards-pragma-once- Use#pragma oncein every headerproj-avoid-circular-includes- Avoid circular includes via forward declarationsproj-modules-adoption- Consider C++20 modules where toolchain support allowsproj-minimal-includes- Include only what you use; forward-declareproj-namespace-per-library- Wrap library code in a project namespaceproj-cmake-target-based- Use modern target-based CMakeproj-separate-public-private-headers- Separate public and internal headersproj-precompiled-headers-large-builds- Use PCH/unity builds only after profiling
14. Linting & Static Analysis (LOW)
lint-clang-tidy-baseline- Run clang-tidy with a curated check baselinelint-compiler-warnings-as-errors- Compile with-Wall -Wextra -Wpedantic -Werrorlint-address-sanitizer- Build and test regularly with AddressSanitizerlint-undefined-behavior-sanitizer- Build and test with UndefinedBehaviorSanitizerlint-thread-sanitizer- Build and test concurrent code with ThreadSanitizerlint-cppcheck-static-analysis- Run cppcheck as a second opinionlint-clang-format-consistent- Enforce a single.clang-formatstylelint-warning-free-baseline- Treat new warnings as build failureslint-include-what-you-use-tool- Run include-what-you-use to keep includes minimal
15. Anti-patterns (REFERENCE)
anti-raw-new-delete- Don't use rawnew/deletefor ownershipanti-c-style-cast- Don't use C-style castsanti-using-namespace-std-header- Don't putusing namespace std;in headersanti-output-parameters- Don't use output parameters when you can return a valueanti-god-class- Don't build God classes with too many responsibilitiesanti-manual-memory-raii-available- Don't hand-manage memory when RAII sufficesanti-macro-for-constants- Don't use#definefor constantsanti-macro-for-functions- Don't use function-like macros over templates/inline functionsanti-naked-new-in-constructor- Don't leak resources when a constructor throwsanti-shared-ptr-everywhere- Don't reach forshared_ptras the defaultanti-catch-all-swallow- Don't write emptycatch(...)blocksanti-void-star-type-erasure- Don't usevoid*when templates/variant/anyexistanti-non-virtual-destructor-base- Don't give a polymorphic base a public non-virtual destructoranti-slicing-by-value- Don't pass/store polymorphic types by valueanti-global-mutable-state- Don't rely on mutable global/static state
Recommended Tooling & Config
CMakeLists.txt warnings and sanitizers
add_library(myproject_warnings INTERFACE)
target_compile_options(myproject_warnings INTERFACE
$<$<CXX_COMPILER_ID:GNU,Clang>:-Wall -Wextra -Wpedantic -Wshadow
-Wconversion -Wsign-conversion -Wnon-virtual-dtor -Wold-style-cast
-Woverloaded-virtual -Wnull-dereference -Wdouble-promotion
-Werror>
$<$<CXX_COMPILER_ID:MSVC>:/W4 /permissive- /WX>
)
option(ENABLE_SANITIZERS "Build with ASan+UBSan" OFF)
if(ENABLE_SANITIZERS)
add_compile_options(-fsanitize=address,undefined -fno-omit-frame-pointer)
add_link_options(-fsanitize=address,undefined)
endif()
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
target_link_libraries(my_target PRIVATE myproject_warnings)
.clang-tidy
Checks: >
-*,
bugprone-*,
clang-analyzer-*,
cppcoreguidelines-*,
-cppcoreguidelines-avoid-magic-numbers,
modernize-*,
-modernize-use-trailing-return-type,
performance-*,
portability-*,
readability-*,
-readability-magic-numbers,
-readability-identifier-length
WarningsAsErrors: 'bugprone-*,clang-analyzer-*,cppcoreguidelines-slicing'
HeaderFilterRegex: '^(include|src)/'
FormatStyle: file
How to Use
This skill provides rule identifiers for quick reference. When generating or reviewing C++ code:
- Check relevant category based on task type
- Apply rules with matching prefix
- Prioritize CRITICAL > HIGH > MEDIUM > LOW
- Read rule files in
rules/for detailed examples
Rule Application by Task
| Task | Primary Categories |
|---|---|
| New class/struct | raii-, own-, api- |
| New free function | err-, name-, type- |
| Ownership/lifetime review | own-, mem-, raii- |
| Error handling | err-, api- |
| Generic/template code | tmpl-, type- |
| Concurrent code | conc-, own-, mem- |
| Performance tuning | perf-, mem-, conc- |
| Code review | anti-, lint- |
Related Skills
- design-patterns - choosing and implementing GoF and idiomatic design patterns (also covers C++: RAII-based patterns, CRTP, PIMPL).
- security-review - security-audit checklists (memory safety, integer overflow, injection, concurrency hazards) for reviewing/auditing C++.
c-coding- sibling skill for plain C (manual memory management, no classes/templates/exceptions, C ABI). Usecpp-codingfor idiomatic modern C++ with RAII, smart pointers, templates, and the STL; usec-codingwhen the codebase is C or a C-compatible subset.
Sources
This skill synthesizes best practices from:
- C++ Core Guidelines (Stroustrup/Sutter)
- Effective Modern C++ by Scott Meyers
- cppreference.com per-standard feature documentation
- CERT C++ Coding Standard
- Production codebases: LLVM, Chromium, Abseil, Folly
- clang-tidy /
cppcoreguidelines-*andmodernize-*check documentation - Community conventions (2024-2026)
What ships with it: 176 files
342.1 KB alongside SKILL.md
rules/
- anti-catch-all-swallow.md1.1 KB
- anti-c-style-cast.md1.1 KB
- anti-global-mutable-state.md1.4 KB
- anti-god-class.md1.7 KB
- anti-macro-for-constants.md1.1 KB
- anti-macro-for-functions.md1.3 KB
- anti-manual-memory-raii-available.md1.3 KB
- anti-naked-new-in-constructor.md1.4 KB
- anti-non-virtual-destructor-base.md1.5 KB
- anti-output-parameters.md1.2 KB
- anti-raw-new-delete.md1.2 KB
- anti-shared-ptr-everywhere.md1.3 KB
- anti-slicing-by-value.md1.5 KB
- anti-using-namespace-std-header.md1.3 KB
- anti-void-star-type-erasure.md1.6 KB
- api-avoid-stl-across-abi.md2.1 KB
- api-consistent-overload-set.md2.2 KB
- api-const-correctness.md2.0 KB
- api-default-member-init.md1.9 KB
- api-deprecated-attribute.md1.8 KB
- api-explicit-constructors.md2.2 KB
- api-header-only-inline.md1.8 KB
- api-interface-segregation.md2.0 KB
- api-nodiscard-return.md2.1 KB
- api-pass-by-value-sink-ref-view.md2.0 KB
- api-pimpl-abi-stability.md2.3 KB
- api-return-value-not-out-param.md2.0 KB
- api-rule-of-zero-value-types.md1.6 KB
- api-strong-types-over-bool.md2.0 KB
- conc-async-future-tasks.md2.1 KB
- conc-atomic-for-simple-state.md2.1 KB
- conc-avoid-data-races.md1.9 KB
- conc-avoid-detach.md2.0 KB
- conc-condition-variable-predicate.md2.0 KB
- conc-coroutines-async-io.md2.3 KB
- conc-immutable-sharing.md2.1 KB
- conc-jthread-over-thread.md1.6 KB
- conc-lock-guard-raii.md1.6 KB
- conc-lock-ordering-deadlock.md2.1 KB
- conc-memory-order-relaxed-care.md2.5 KB
136 more files not listed here. See all 176 in the repository.