Back to skills
SKILL.md
C Ecosystem 1
ASecurityThis skill should be used when working with C++ projects, CMakeLists.txt, Ninja, clang-tidy, clang-format, GoogleTest, Catch2, or Modern C++ (C++11-23) language patterns. Provides comprehensive C++ ecosystem patterns and best practices.
- 2 stars
- 0 votes
- 0 copies
- 0 views
- Added September 27, 2026
Works with
Security analysis
100/100npx -y skills add David-Li0406/meta-skill-evloving --skill c-ecosystem-1 --agent claude-codeAre you the author of C Ecosystem 1?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/david-li0406-c-ecosystem-1)---
name: C++ Ecosystem
description: This skill should be used when working with C++ projects, CMakeLists.txt, Ninja, clang-tidy, clang-format, GoogleTest, Catch2, or Modern C++ (C++11-23) language patterns. Provides comprehensive C++ ecosystem patterns and best practices.
---
<purpose>
Provide comprehensive patterns for Modern C++ (C++11-23) language, CMake build system, and toolchain configuration.
</purpose>
<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>
</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</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>
<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>
</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.0+)</description>
<example>
cmake_minimum_required(VERSION 3.20)
project(MyProject VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
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_20)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE mylib)
</example>
</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</description>
<flags>
<flag name="-std=c++20">Enable C++20 standard</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>
<flags>
<flag name="-std=c++20">Enable C++20 standard</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</description>
<usage>clang-tidy src/*.cpp -- -std=c++20</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</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++20
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>resolve-library-id libraryName="cppreference"</step>
<step>get-library-docs context7CompatibleLibraryID="/websites/cppreference_com" topic="std::unique_ptr"</step>
</pattern>
<pattern name="cmake_reference">
<step>get-library-docs context7CompatibleLibraryID="/Kitware/CMake" topic="target_link_libraries"</step>
</pattern>
<pattern name="testing_reference">
<step>get-library-docs context7CompatibleLibraryID="/google/googletest" topic="assertions"</step>
</pattern>
</usage_patterns>
</context7_integration>
<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>1. Check CMakeLists.txt for build configuration</step>
<step>2. Review existing code patterns and standards</step>
<step>3. Identify memory management requirements</step>
</phase>
<phase name="implement">
<objective>Write modern, safe C++ code</objective>
<step>1. Use RAII and smart pointers</step>
<step>2. Follow C++ Core Guidelines</step>
<step>3. Prefer standard library over raw implementations</step>
</phase>
<phase name="validate">
<objective>Verify C++ code correctness</objective>
<step>1. Build with warnings enabled</step>
<step>2. Run static analysis tools</step>
<step>3. Execute tests with sanitizers</step>
</phase>
</workflow>
<error_escalation>
<level severity="low">
<example>Compiler warning about unused variable</example>
<action>Fix warning, maintain clean build</action>
</level>
<level severity="medium">
<example>Compilation error</example>
<action>Fix error, verify with full build</action>
</level>
<level severity="high">
<example>Memory leak or undefined behavior detected</example>
<action>Stop, require safe memory management</action>
</level>
<level severity="critical">
<example>Buffer overflow or security vulnerability</example>
<action>Block operation, require immediate fix</action>
</level>
</error_escalation>
<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_agents>
<agent name="design">Architecture design for C++ class hierarchies and template metaprogramming</agent>
<agent name="docs">Doxygen documentation and API reference generation</agent>
<agent name="execute">CMake configuration and C++ implementation tasks</agent>
<agent name="bug">Debugging memory leaks, segfaults, and undefined behavior</agent>
</related_agents>
<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>
Attribution
Comments
Loading comments…