home-manager/ai-tools/agent-skills/skills/cplusplus-ecosystem/SKILL.md
This skill should be used when working with C++ projects, CMakeLists.txt, Ninja, clang-tidy, clang-format, GoogleTest, Catch2, or Modern C++ (C++20/23/26) language patterns. Provides comprehensive C++ ecosystem patterns and best practices.
npx skillsauth add takeokunn/nixos-configuration C++ EcosystemInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
<cplusplus_language> <modern_features> <decision_tree name="when_to_use"> <question>Are you working with modern C++ features like smart pointers, move semantics, or ranges?</question> <if_yes>Apply modern C++ patterns for safer, more efficient code</if_yes> <if_no>Consider refactoring legacy code to modern C++ standards</if_no> </decision_tree>
<concept name="move_semantics">
<description>Transfer ownership of resources without copying. Introduced in C++11.</description>
<example>
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1); // v1 is now empty
</example>
<use>Use std::move for expensive-to-copy objects when ownership transfer is intended</use>
</concept>
<concept name="smart_pointers">
<description>RAII-based automatic memory management</description>
<types>
<type name="unique_ptr">Exclusive ownership, zero overhead</type>
<type name="shared_ptr">Shared ownership with reference counting</type>
<type name="weak_ptr">Non-owning observer of shared_ptr</type>
</types>
<example>
auto ptr = std::make_unique<MyClass>(args);
auto shared = std::make_shared<MyClass>(args);
</example>
</concept>
<concept name="constexpr">
<description>Compile-time computation</description>
<evolution>
<version name="C++11">Simple expressions only</version>
<version name="C++14">Loops and local variables allowed</version>
<version name="C++17">if constexpr for compile-time branching</version>
<version name="C++20">constexpr std::vector, std::string</version>
<version name="C++23">if consteval for context detection, constexpr std::bitset/std::unique_ptr</version>
</evolution>
</concept>
<concept name="auto_type_deduction">
<description>Compiler deduces type from initializer</description>
<example>
auto x = 42; // int
auto vec = std::vector<int>{}; // std::vector<int>
auto [key, value] = pair; // structured bindings (C++17)
</example>
</concept>
<concept name="lambdas">
<description>Anonymous function objects</description>
<example>
auto add = [](int a, int b) { return a + b; };
auto capture_by_ref = [&x]() { x++; };
auto capture_by_val = [=]() { return x; };
auto generic = [](auto a, auto b) { return a + b; }; // C++14
</example>
</concept>
<concept name="concepts">
<description>Constraints on template parameters (C++20)</description>
<example>
template<typename T>
concept Addable = requires(T a, T b) { a + b; };
template<Addable T>
T add(T a, T b) { return a + b; }
</example>
</concept>
<concept name="ranges">
<description>Composable range operations (C++20)</description>
<example>
auto result = numbers
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * 2; });
</example>
</concept>
<concept name="modules">
<description>C++20 modules for faster compilation and better encapsulation</description>
<example>
// math.cppm (module interface)
export module math;
export int add(int a, int b) { return a + b; }
// main.cpp
import math;
int main() { return add(1, 2); }
</example>
<note>Requires CMake 3.28+ with CMAKE_CXX_SCAN_FOR_MODULES. GCC 15+ and Clang 18+ have production-ready support. Use CMake 3.30+ for import std; support (set CMAKE_CXX_MODULE_STD ON).</note>
</concept>
<concept name="coroutines">
<description>C++20 coroutines for async and generator patterns</description>
<example>
#include <coroutine>
generator<int> range(int start, int end) {
for (int i = start; i < end; ++i) {
co_yield i;
}
}
task<int> async_compute() {
co_return co_await some_async_operation();
}
</example>
<note>Requires coroutine library (cppcoro, libcoro, or custom promise types)</note>
</concept>
<concept name="three_way_comparison">
<description>C++20 spaceship operator for simplified comparisons</description>
<example>
struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};
// Automatically generates ==, !=, <, >, <=, >=
</example>
</concept>
<concept name="vocabulary_types">
<description>C++17 vocabulary types for safer value handling</description>
<types>
<type name="std::optional">Maybe-value container, replaces nullable pointers</type>
<type name="std::variant">Type-safe union, replaces raw unions</type>
<type name="std::any">Type-erased container for any single value</type>
</types>
<example>
std::optional<int> find_value(const std::vector<int>& v, int target) {
auto it = std::find(v.begin(), v.end(), target);
if (it != v.end()) return *it;
return std::nullopt;
}
std::variant<int, std::string, double> data = 42;
std::visit([](auto&& val) { std::cout << val; }, data);
</example>
</concept>
</modern_features>
<cpp26_features> <description>C++26 features are progressively landing across major toolchains. Prefer feature detection and compiler checks over hard assumptions.</description> <feature name="reflection"> <description>Static reflection via the ^^ operator (cat-ears operator). The biggest upgrade for C++ development since templates.</description> <example> consteval auto get_member_names(auto T) { return members_of(^^T); } </example> <compiler_flag>-std=c++2c</compiler_flag> <note>GCC 16 has reflection merged in trunk. Experimental Clang fork by Dan Katz also available.</note> </feature> <feature name="contracts"> <description>Contract assertions with contract_assert keyword, plus pre and post conditions.</description> <example> int divide(int a, int b) pre(b != 0) post(r: r * b == a) { contract_assert(b != 0); return a / b; } </example> <note>GCC has contracts merged in trunk, awaiting release.</note> </feature> <feature name="std_execution"> <description>std::execution (P2300) — sender/receiver model for structured async and parallel programming. Replaces ad-hoc async patterns with composable, type-safe pipelines.</description> <example> #include <execution>
auto work = std::execution::schedule(scheduler)
| std::execution::then([] { return compute(); })
| std::execution::then([](auto result) { return process(result); });
std::execution::sync_wait(std::move(work));
</example>
<note>stdexec (formerly libunifex) provides a reference implementation. Shipping in GCC 16 and libc++.</note>
</feature>
<feature name="pattern_matching">
<description>Pattern matching (P2688) — not approved for C++26. Expected for C++29. Use std::visit with std::variant as the current alternative.</description>
</feature>
</cpp26_features>
<cpp23_features> <description>C++23 is fully stable and well-supported by GCC 14+, Clang 18+, and MSVC 17.10+. Use -std=c++23 confidently in production.</description>
<feature name="std_expected">
<description>std::expected — monadic error handling, superior to exceptions for expected failure paths</description>
<example>
#include <expected>
std::expected<int, std::string> parse_int(std::string_view sv) {
int val;
auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), val);
if (ec != std::errc{}) return std::unexpected("parse error");
return val;
}
auto result = parse_int("42")
.transform([](int v) { return v * 2; })
.transform_error([](auto e) { return "failed: " + e; });
</example>
</feature>
<feature name="std_print">
<description>std::print / std::println — type-safe formatted output, replaces iostream and printf</description>
<example>
#include <print>
std::println("Hello, {}!", "world");
std::print("x = {}, y = {}\n", 1, 2);
</example>
</feature>
<feature name="flat_containers">
<description>std::flat_map / std::flat_set — cache-friendly sorted containers backed by contiguous storage</description>
<example>
#include <flat_map>
#include <flat_set>
std::flat_map<std::string, int> scores;
scores["alice"] = 100;
std::flat_set<int> ids = {3, 1, 4, 1, 5};
</example>
<note>Better performance than std::map/std::set for small-to-medium collections due to cache locality.</note>
</feature>
<feature name="deducing_this">
<description>Explicit object parameter (deducing this) — eliminates CRTP boilerplate, enables recursive lambdas</description>
<example>
struct Widget {
template<typename Self>
auto&& name(this Self&& self) {
return std::forward<Self>(self).name_;
}
private:
std::string name_;
};
// Recursive lambda
auto fib = [](this auto self, int n) -> int {
return n < 2 ? n : self(n - 1) + self(n - 2);
};
</example>
</feature>
<feature name="std_generator">
<description>std::generator — standard coroutine generator, no more custom promise types needed</description>
<example>
#include <generator>
std::generator<int> fibonacci() {
int a = 0, b = 1;
while (true) {
co_yield a;
auto tmp = a;
a = b;
b += tmp;
}
}
</example>
</feature>
<feature name="import_std">
<description>import std; — import the entire standard library as a module. Dramatically improves compile times.</description>
<example>
import std;
int main() {
std::println("Hello from modules!");
std::vector<int> v = {1, 2, 3};
}
</example>
<note>Requires CMake 3.30+ and compiler support. GCC 15+, Clang 18+ with libc++. Set CMAKE_CXX_MODULE_STD ON.</note>
</feature>
<feature name="std_stacktrace">
<description>std::stacktrace — portable stack trace capture for diagnostics</description>
<example>
#include <stacktrace>
void log_error(std::string_view msg) {
std::println(stderr, "Error: {}\nStack trace:\n{}", msg, std::stacktrace::current());
}
</example>
<note>Link with -lstdc++_libbacktrace on GCC.</note>
</feature>
<feature name="if_consteval">
<description>if consteval — detect compile-time evaluation context, replacing std::is_constant_evaluated()</description>
<example>
constexpr int compute(int x) {
if consteval {
// compile-time path
return x * x;
} else {
// runtime path, can use non-constexpr operations
return fast_runtime_compute(x);
}
}
</example>
</feature>
<feature name="multidimensional_subscript">
<description>Multidimensional subscript operator — operator[] with multiple arguments</description>
<example>
template<typename T>
class Matrix {
std::vector<T> data_;
size_t cols_;
public:
T& operator[](size_t row, size_t col) {
return data_[row * cols_ + col];
}
};
Matrix<double> m(3, 3);
m[1, 2] = 3.14;
</example>
</feature>
</cpp23_features>
<concurrency> <decision_tree name="when_to_use"> <question>Do you need concurrent or parallel execution?</question> <if_yes>Use std::thread for explicit control, std::async for task-based parallelism, or atomics for lock-free synchronization</if_yes> <if_no>Use single-threaded sequential execution for simplicity</if_no> </decision_tree><concept name="threads">
<description>Thread creation and management</description>
<example>
std::thread t([]{ /* work */ });
t.join(); // or t.detach()
auto future = std::async(std::launch::async, []{ return 42; });
int result = future.get();
</example>
</concept>
<concept name="mutexes">
<description>Mutual exclusion for shared data</description>
<example>
std::mutex mtx;
std::lock_guard<std::mutex> lock(mtx); // RAII lock
std::shared_mutex rw_mtx;
std::shared_lock<std::shared_mutex> read_lock(rw_mtx); // multiple readers
std::unique_lock<std::shared_mutex> write_lock(rw_mtx); // exclusive writer
</example>
</concept>
<concept name="atomics">
<description>Lock-free atomic operations</description>
<example>
std::atomic<int> counter{0};
counter.fetch_add(1, std::memory_order_relaxed);
counter.store(10, std::memory_order_release);
int val = counter.load(std::memory_order_acquire);
</example>
</concept>
<concept name="condition_variables">
<description>Thread synchronization primitives</description>
<example>
std::condition_variable cv;
std::mutex mtx;
bool ready = false;
// Waiting thread
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return ready; });
// Notifying thread
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
</example>
</concept>
<anti_patterns>
<avoid name="data_races">
<description>Accessing shared data without synchronization</description>
<instead>Use mutex, atomic, or immutable data</instead>
</avoid>
<avoid name="deadlocks">
<description>Circular lock dependencies</description>
<instead>Use std::scoped_lock for multiple mutexes, consistent lock ordering</instead>
</avoid>
</anti_patterns>
</concurrency>
<patterns>
<pattern name="raii">
<description>Resource Acquisition Is Initialization - bind resource lifetime to object lifetime</description>
<example>
class FileHandle {
FILE* file_;
public:
explicit FileHandle(const char* path) : file_(fopen(path, "r")) {}
~FileHandle() { if (file_) fclose(file_); }
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
};
</example>
<use_case>Managing resources: files, sockets, locks, memory</use_case>
</pattern>
<pattern name="rule_of_zero">
<description>Prefer classes that do not define special member functions</description>
<example>
class Person {
std::string name_;
std::vector<std::string> addresses_;
// No destructor, copy/move constructors, or assignment operators needed
};
</example>
<use_case>Use smart pointers and standard containers; let compiler generate defaults</use_case>
</pattern>
<pattern name="rule_of_five">
<description>If you define one of destructor, copy/move constructor, or copy/move assignment, define all five</description>
<example>
class Resource {
int* data_;
public:
Resource();
~Resource();
Resource(const Resource&);
Resource(Resource&&) noexcept;
Resource& operator=(const Resource&);
Resource& operator=(Resource&&) noexcept;
};
</example>
<use_case>Classes managing raw resources directly</use_case>
</pattern>
<pattern name="pimpl">
<description>Pointer to Implementation - hide implementation details and reduce compilation dependencies</description>
<example>
// header
class Widget {
class Impl;
std::unique_ptr<Impl> pimpl_;
public:
Widget();
~Widget();
void doSomething();
};
// source
class Widget::Impl {
// implementation details
};
</example>
<use_case>Reducing compile times, ABI stability, hiding implementation</use_case>
</pattern>
<pattern name="crtp">
<description>Curiously Recurring Template Pattern - static polymorphism</description>
<example>
template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
class Derived : public Base<Derived> {
public:
void implementation() { /_ ... _/ }
};
</example>
<use_case>Static polymorphism, mixin classes, compile-time polymorphism</use_case>
</pattern>
<pattern name="type_erasure">
<description>Hide concrete types behind a uniform interface</description>
<example>
class AnyCallable {
struct Concept {
virtual ~Concept() = default;
virtual void call() = 0;
};
template<typename T>
struct Model : Concept {
T obj_;
void call() override { obj_(); }
};
std::unique_ptr<Concept> ptr_;
public:
template<typename T>
AnyCallable(T obj) : ptr_(std::make_unique<Model<T>>(std::move(obj))) {}
};
</example>
<use_case>std::function, std::any, runtime polymorphism without inheritance</use_case>
</pattern>
</patterns>
<anti_patterns> <avoid name="raw_pointer_ownership"> <description>Using raw pointers for ownership</description> <instead>Use std::unique_ptr or std::shared_ptr</instead> </avoid>
<avoid name="manual_memory_management">
<description>Using new/delete directly</description>
<instead>Use std::make_unique/std::make_shared</instead>
</avoid>
<avoid name="c_style_casts">
<description>Using (Type)value casts</description>
<instead>Use static_cast, dynamic_cast, const_cast, or reinterpret_cast</instead>
</avoid>
<avoid name="using_namespace_in_headers">
<description>Using using namespace std; in headers</description>
<instead>Use fully qualified names or limited using declarations in source files</instead>
</avoid>
<avoid name="throwing_in_destructors">
<description>Throwing exceptions in destructors</description>
<instead>Mark destructors noexcept, handle errors internally</instead>
</avoid>
<avoid name="const_cast_abuse">
<description>Using const_cast to remove const from data you do not own</description>
<instead>Fix the design to avoid needing const_cast</instead>
</avoid>
<avoid name="manual_raii">
<description>Writing custom destructors for resource management when standard smart pointers suffice</description>
<instead>Use std::unique_ptr with custom deleters, or Rule of Zero with standard containers and smart pointers</instead>
</avoid>
</anti_patterns> </cplusplus_language>
<cmake> <decision_tree name="when_to_use"> <question>Are you building a C++ project with dependencies and multiple targets?</question> <if_yes>Use CMake for cross-platform, modern build configuration</if_yes> <if_no>Use simple Makefile for single-file projects or prototypes</if_no> </decision_tree><project_structure> <standard_layout> . ├── CMakeLists.txt ├── cmake/ │ └── modules/ ├── src/ │ ├── CMakeLists.txt │ ├── main.cpp │ └── lib/ ├── include/ │ └── project/ ├── tests/ │ ├── CMakeLists.txt │ └── test_*.cpp └── build/ </standard_layout> </project_structure>
<cmake_patterns> <pattern name="modern_cmake"> <description>Target-based CMake (3.30+ recommended for C++23/26 and module support)</description> <example> cmake_minimum_required(VERSION 3.30) project(MyProject VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_library(mylib STATIC src/mylib.cpp)
target_include_directories(mylib PUBLIC include)
target_compile_features(mylib PUBLIC cxx_std_23)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)
</example>
</pattern>
<pattern name="cmake_presets">
<description>CMakePresets.json for reproducible builds (CMake 3.21+, widely adopted)</description>
<example>
// CMakePresets.json
{
"version": 6,
"configurePresets": [
{
"name": "default",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/${presetName}",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "23",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON"
}
},
{
"name": "release",
"inherits": "default",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release"
}
}
],
"buildPresets": [
{ "name": "default", "configurePreset": "default" },
{ "name": "release", "configurePreset": "release" }
]
}
</example>
<usage>cmake --preset default && cmake --build --preset default</usage>
</pattern>
<pattern name="package_management">
<description>Use vcpkg or Conan 2.x for dependency management</description>
<vcpkg>
<usage>cmake -B build -DCMAKE_TOOLCHAIN_FILE=$VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake</usage>
<manifest>vcpkg.json declares dependencies; integrates seamlessly with CMake presets</manifest>
</vcpkg>
<conan>
<usage>conan install . --output-folder=build --build=missing</usage>
<note>Conan 2.x (not 1.x) — uses conanfile.py or conanfile.txt with CMake generators</note>
</conan>
</pattern>
<pattern name="find_package">
<description>Finding and using external dependencies</description>
<example>
find_package(Threads REQUIRED)
find_package(GTest REQUIRED)
target_link_libraries(myapp PRIVATE Threads::Threads)
target_link_libraries(mytests PRIVATE GTest::gtest GTest::gtest_main)
</example>
</pattern>
<pattern name="compiler_options">
<description>Setting compiler warnings and options</description>
<example>
add_library(project_warnings INTERFACE)
target_compile_options(project_warnings INTERFACE
$<$<CXX_COMPILER_ID:GNU,Clang>:
-Wall -Wextra -Wpedantic -Werror
-Wshadow -Wnon-virtual-dtor -Wold-style-cast
-Wcast-align -Wunused -Woverloaded-virtual
-Wconversion -Wsign-conversion -Wnull-dereference
>
)
</example>
</pattern>
</cmake_patterns>
<commands> <command name="cmake -B build -G Ninja">Configure with Ninja generator</command> <command name="cmake --build build">Build the project</command> <command name="cmake --build build --target test">Run tests</command> <command name="cmake --build build --config Release">Build in Release mode</command> <command name="cmake --install build --prefix /usr/local">Install the project</command> </commands> </cmake> <toolchain> <compilers> <compiler name="clang"> <description>LLVM C++ compiler (Clang 19+ has comprehensive C++23 support)</description> <flags> <flag name="-std=c++20">Enable C++20 standard</flag> <flag name="-std=c++23">Enable C++23 standard (widely supported)</flag> <flag name="-std=c++2c">Enable C++26 standard (experimental)</flag> <flag name="-stdlib=libc++">Use LLVM libc++ standard library</flag> <flag name="-Wall -Wextra -Wpedantic">Enable comprehensive warnings</flag> <flag name="-Werror">Treat warnings as errors</flag> <flag name="-fsanitize=address,undefined">Enable sanitizers</flag> </flags> </compiler><compiler name="gcc">
<description>GNU C++ compiler</description>
<defaults>
<default name="GCC 16">Default is C++20 mode (was C++17 before)</default>
<default name="GCC 15">C23 is the default for C mode</default>
</defaults>
<flags>
<flag name="-std=c++20">Enable C++20 standard (default in GCC 16)</flag>
<flag name="-std=c++23">Enable C++23 standard (widely supported)</flag>
<flag name="-std=c++2c or -std=gnu++2c">Enable C++26 standard (experimental)</flag>
<flag name="-Wall -Wextra -Wpedantic">Enable comprehensive warnings</flag>
<flag name="-Werror">Treat warnings as errors</flag>
<flag name="-fsanitize=address,undefined">Enable sanitizers</flag>
<flag name="-fanalyzer">Enable static analysis (GCC 10+)</flag>
</flags>
</compiler>
</compilers>
<clang_tidy> <description>Static analysis and linting tool (use clang-tidy 19+ for C++23 support)</description> <usage>clang-tidy src/*.cpp -- -std=c++23</usage>
<configuration>
<file_reference>.clang-tidy</file_reference>
Checks: >
-*,
bugprone-*,
clang-analyzer-*,
cppcoreguidelines-*,
modernize-*,
performance-*,
readability-*,
-modernize-use-trailing-return-type
WarningsAsErrors: '_'
HeaderFilterRegex: '._'
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: CamelCase
- key: readability-identifier-naming.FunctionCase
value: camelBack
- key: readability-identifier-naming.VariableCase
value: lower_case
</configuration>
<common_checks>
<check name="modernize-use-nullptr">Replace NULL with nullptr</check>
<check name="modernize-use-auto">Use auto where appropriate</check>
<check name="modernize-use-override">Use override keyword</check>
<check name="modernize-loop-convert">Convert C-style loops to range-based</check>
<check name="cppcoreguidelines-owning-memory">Check ownership semantics</check>
<check name="bugprone-use-after-move">Detect use-after-move bugs</check>
<check name="performance-unnecessary-copy-initialization">Detect unnecessary copies</check>
</common_checks>
</clang_tidy>
<clang_format> <description>Code formatting tool (use clang-format 19+ for C++23 syntax support)</description> <usage>clang-format -i src/.cpp include/.hpp</usage>
<configuration>
<file_reference>.clang-format</file_reference>
BasedOnStyle: LLVM
IndentWidth: 4
ColumnLimit: 100
Language: Cpp
Standard: c++23
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AllowShortFunctionsOnASingleLine: Inline
BreakBeforeBraces: Attach
IncludeBlocks: Regroup
IncludeCategories:
- Regex: '^<.*>'
Priority: 1
- Regex: '^".*"'
Priority: 2
PointerAlignment: Left
SortIncludes: CaseSensitive
</configuration>
</clang_format>
<sanitizers> <description>Runtime error detection tools</description><sanitizer name="AddressSanitizer">
<description>Detects memory errors (buffer overflow, use-after-free)</description>
<flags>-fsanitize=address -fno-omit-frame-pointer</flags>
<cmake>
target_compile_options(myapp PRIVATE -fsanitize=address -fno-omit-frame-pointer)
target_link_options(myapp PRIVATE -fsanitize=address)
</cmake>
</sanitizer>
<sanitizer name="UndefinedBehaviorSanitizer">
<description>Detects undefined behavior (signed overflow, null dereference)</description>
<flags>-fsanitize=undefined</flags>
<cmake>
target_compile_options(myapp PRIVATE -fsanitize=undefined)
target_link_options(myapp PRIVATE -fsanitize=undefined)
</cmake>
</sanitizer>
<sanitizer name="ThreadSanitizer">
<description>Detects data races and deadlocks</description>
<flags>-fsanitize=thread</flags>
<note>Cannot be combined with AddressSanitizer</note>
</sanitizer>
<sanitizer name="MemorySanitizer">
<description>Detects uninitialized memory reads (Clang only)</description>
<flags>-fsanitize=memory</flags>
<note>Requires all code and libraries to be instrumented</note>
</sanitizer>
<cmake_preset>
# CMakePresets.json sanitizer configuration
{
"configurePresets": [{
"name": "sanitize",
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer"
}
}]
}
</cmake_preset>
</sanitizers>
</toolchain>
<testing>
<decision_tree name="when_to_use">
<question>Do you need unit testing for C++ code?</question>
<if_yes>Use GoogleTest for comprehensive testing features or Catch2 for header-only simplicity</if_yes>
<if_no>Consider adding tests to improve code quality and maintainability</if_no>
</decision_tree>
<googletest>
<description>Google Test framework</description>
<cmake_integration>
enable_testing()
find_package(GTest REQUIRED)
add_executable(tests tests/test_main.cpp)
target_link_libraries(tests PRIVATE GTest::gtest GTest::gtest_main)
include(GoogleTest)
gtest_discover_tests(tests)
</cmake_integration>
<example>
#include <gtest/gtest.h>
TEST(MyTest, BasicAssertion) {
EXPECT_EQ(1 + 1, 2);
}
TEST(MyTest, StringComparison) {
std::string s = "hello";
EXPECT_STREQ(s.c_str(), "hello");
}
class MyFixture : public ::testing::Test {
protected:
void SetUp() override { /_ setup _/ }
void TearDown() override { /_ cleanup _/ }
};
TEST_F(MyFixture, FixtureTest) {
EXPECT_TRUE(true);
}
</example>
</googletest>
<catch2>
<description>Catch2 test framework</description>
<cmake_integration>
find_package(Catch2 3 REQUIRED)
add_executable(tests tests/test_main.cpp)
target_link_libraries(tests PRIVATE Catch2::Catch2WithMain)
include(CTest)
include(Catch)
catch_discover_tests(tests)
</cmake_integration>
<example>
#include <catch2/catch_test_macros.hpp>
TEST_CASE("Basic arithmetic", "[math]") {
REQUIRE(1 + 1 == 2);
CHECK(2 * 2 == 4);
}
TEST_CASE("String operations", "[string]") {
std::string s = "hello";
SECTION("length") {
REQUIRE(s.length() == 5);
}
SECTION("comparison") {
REQUIRE(s == "hello");
}
}
</example>
</catch2>
</testing>
<context7_integration> <description>Use Context7 MCP for up-to-date C++ documentation</description>
<cplusplus_libraries> <library name="cppreference" id="/websites/cppreference_com" /> <library name="CMake" id="/Kitware/CMake" /> <library name="GoogleTest" id="/google/googletest" /> <library name="Catch2" id="/catchorg/Catch2" /> </cplusplus_libraries>
<usage_patterns> <pattern name="language_reference"> <step order="1"> <action>resolve-library-id libraryName="cppreference"</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>get-library-docs context7CompatibleLibraryID="/websites/cppreference_com" topic="std::unique_ptr"</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> </pattern>
<pattern name="cmake_reference">
<step order="1">
<action>get-library-docs context7CompatibleLibraryID="/Kitware/CMake" topic="target_link_libraries"</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> </pattern>
<pattern name="testing_reference">
<step order="1">
<action>get-library-docs context7CompatibleLibraryID="/google/googletest" topic="assertions"</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> </pattern> </usage_patterns> </context7_integration>
<rules priority="critical"> <rule>Always compile with `-Wall -Wextra -Wpedantic` and treat warnings as errors in CI</rule> <rule>Use RAII for all resource management; never use raw `new`/`delete` outside smart pointer factory</rule> <rule>Run sanitizers (AddressSanitizer, UBSan) in debug builds</rule> <rule>Target C++23 as the stable baseline; enable C++26 features only when compiler support is confirmed (Clang 20+ / GCC 15+)</rule> </rules> <rules priority="standard"> <rule>Prefer `std::span` over raw pointer+length parameters for buffer arguments</rule> <rule>Use `[[nodiscard]]` on functions whose return values must not be silently discarded</rule> <rule>Run `clang-format` and `clang-tidy` before committing</rule> </rules><best_practices> <practice priority="critical">Use smart pointers instead of raw pointers for ownership</practice> <practice priority="critical">Enable -Wall -Wextra -Werror for all builds</practice> <practice priority="critical">Run clang-tidy before committing</practice> <practice priority="critical">Format with clang-format for consistent style</practice> <practice priority="standard">Prefer const correctness throughout</practice> <practice priority="standard">Use noexcept for move constructors and destructors</practice> <practice priority="standard">Prefer constexpr for compile-time computation</practice> <practice priority="standard">Use std::string_view for non-owning string references</practice> <practice priority="standard">Prefer range-based for loops over index-based</practice> <practice priority="standard">Use structured bindings for tuple/pair access</practice> <practice priority="standard">Document public API with Doxygen comments</practice> <practice priority="standard">Write unit tests alongside implementation</practice> </best_practices>
<workflow> <phase name="analyze"> <objective>Understand C++ code requirements</objective> <step order="1"> <action>1. Check CMakeLists.txt for build configuration</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>2. Review existing code patterns and standards</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>3. Identify memory management requirements</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> </phase> <phase name="implement"> <objective>Write modern, safe C++ code</objective> <step order="1"> <action>1. Use RAII and smart pointers</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>2. Follow C++ Core Guidelines</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>3. Prefer standard library over raw implementations</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> </phase> <phase name="validate"> <objective>Verify C++ code correctness</objective> <step order="1"> <action>1. Build with warnings enabled</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>2. Run static analysis tools</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> <step order="1"> <action>3. Execute tests with sanitizers</action> <tool>Workflow guidance</tool> <output>Step completed</output> </step> </phase> </workflow><error_escalation inherits="core-patterns#error_escalation"> <examples> <example severity="low">Compiler warning about unused variable</example> <example severity="medium">Compilation error</example> <example severity="high">Memory leak or undefined behavior detected</example> <example severity="critical">Buffer overflow or security vulnerability</example> </examples> </error_escalation>
<tools> <tool name="Read">Read relevant source files and docs</tool> <tool name="Grep">Search for patterns and references</tool> </tools> <patterns> <pattern name="usage"> <description>Apply this skill when task keywords and domain match</description> <example>Use the canonical workflow and verify with project conventions</example> </pattern> </patterns><decision_tree name="skill_activation"> <question>Does the task clearly match this skill domain?</question> <branch condition="Yes">Use this skill workflow and constraints</branch> <branch condition="No">Use a more appropriate domain skill</branch> </decision_tree>
<related_agents> <agent name="explore">Locate code patterns and references in this skill domain</agent> <agent name="quality-assurance">Review implementation quality against this skill guidance</agent> <agent name="code-quality">Analyze code complexity and suggest refactoring improvements</agent> </related_agents>
<constraints> <must>Use smart pointers for memory management</must> <must>Enable compiler warnings (-Wall -Wextra)</must> <must>Follow C++ Core Guidelines</must> <avoid>Raw pointers for ownership</avoid> <avoid>Manual memory management when smart pointers suffice</avoid> <avoid>Undefined behavior</avoid> </constraints><related_skills> <skill name="serena-usage">Symbol operations for C++ code navigation and refactoring</skill> <skill name="context7-usage">C++ documentation via /websites/cppreference_com and CMake docs via /Kitware/CMake</skill> <skill name="investigation-patterns">Debugging with sanitizers, valgrind, and gdb</skill> <skill name="technical-documentation">Creating library documentation with Doxygen</skill> </related_skills>
tools
This skill should be used when the user asks to parse, search, grep, query, filter, or extract headings, sections, tasks, code blocks, links, or tables from Markdown files. Use when working with mdq, jq-style Markdown querying, section extraction, checklist validation, CI task scripts, or documentation automation pipelines.
development
Practical SBCL (Steel Bank Common Lisp) operations guide. Use this skill whenever the user mentions SBCL execution/debugging, --script usage, REPL workflows, backtraces, ASDF loading, save-lisp-and-die, profiling, or SLY-based Common Lisp development.
tools
Context7 MCP documentation retrieval patterns for up-to-date library and API references. Use this skill whenever current library docs, API signatures, version-specific behavior, or migration notes are needed.
development
Patterns for output formats, reflection checkpoints, agent references, and self-evaluation shared across agents and commands.