Cpp coding
Skill nguyenthdat/opencode-manager/registry/skills/cpp-coding
Project-scoped OpenCode TUI plugin for grouping and managing MCP servers, custom agent skills, and pinned vendor skill registries.
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.
2 things to look at
- 13 days oldThe repository was created 13 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 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.
What its author says it does
Copied from the file, not written here
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.
SKILL.md
28.5 KB, 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)