---
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.
---
Provide comprehensive patterns for Modern C++ (C++11-23) language, CMake build system, and toolchain configuration.
Are you working with modern C++ features like smart pointers, move semantics, or ranges?
Apply modern C++ patterns for safer, more efficient code
Consider refactoring legacy code to modern C++ standards
Transfer ownership of resources without copying. Introduced in C++11.
std::vector<int> v1 = {1, 2, 3};
std::vector<int> v2 = std::move(v1); // v1 is now empty
RAII-based automatic memory management
Exclusive ownership, zero overhead
Shared ownership with reference counting
Non-owning observer of shared_ptr
auto ptr = std::make_unique<MyClass>(args);
auto shared = std::make_shared<MyClass>(args);
Compile-time computation
Simple expressions only
Loops and local variables allowed
if constexpr for compile-time branching
constexpr std::vector, std::string
Compiler deduces type from initializer
auto x = 42; // int
auto vec = std::vector<int>{}; // std::vector<int>
auto [key, value] = pair; // structured bindings (C++17)
Anonymous function objects
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
Constraints on template parameters (C++20)
template<typename T>
concept Addable = requires(T a, T b) { a + b; };
template<Addable T>
T add(T a, T b) { return a + b; }
Composable range operations (C++20)
auto result = numbers
| std::views::filter([](int n) { return n % 2 == 0; })
| std::views::transform([](int n) { return n * 2; });
C++20 modules for faster compilation and better encapsulation
// 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); }
Requires CMake 3.28+ with CMAKE_CXX_SCAN_FOR_MODULES
C++20 coroutines for async and generator patterns
#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();
}
Requires coroutine library (cppcoro, libcoro, or custom promise types)
C++20 spaceship operator for simplified comparisons
struct Point {
int x, y;
auto operator<=>(const Point&) const = default;
};
// Automatically generates ==, !=, <, >, <=, >=
C++17 vocabulary types for safer value handling
Maybe-value container, replaces nullable pointers
Type-safe union, replaces raw unions
Type-erased container for any single value
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);
Do you need concurrent or parallel execution?
Use std::thread for explicit control, std::async for task-based parallelism, or atomics for lock-free synchronization
Use single-threaded sequential execution for simplicity
Thread creation and management
std::thread t([]{ /* work */ });
t.join(); // or t.detach()
auto future = std::async(std::launch::async, []{ return 42; });
int result = future.get();
Mutual exclusion for shared data
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
Lock-free atomic operations
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);
Thread synchronization primitives
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();
Accessing shared data without synchronization
Use mutex, atomic, or immutable data
Circular lock dependencies
Use std::scoped_lock for multiple mutexes, consistent lock ordering
Resource Acquisition Is Initialization - bind resource lifetime to object lifetime
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;
};
Managing resources: files, sockets, locks, memory
Prefer classes that do not define special member functions
class Person {
std::string name_;
std::vector<std::string> addresses_;
// No destructor, copy/move constructors, or assignment operators needed
};
Use smart pointers and standard containers; let compiler generate defaults
If you define one of destructor, copy/move constructor, or copy/move assignment, define all five
class Resource {
int* data_;
public:
Resource();
~Resource();
Resource(const Resource&);
Resource(Resource&&) noexcept;
Resource& operator=(const Resource&);
Resource& operator=(Resource&&) noexcept;
};
Classes managing raw resources directly
Pointer to Implementation - hide implementation details and reduce compilation dependencies
// header
class Widget {
class Impl;
std::unique_ptr<Impl> pimpl_;
public:
Widget();
~Widget();
void doSomething();
};
// source
class Widget::Impl {
// implementation details
};
Reducing compile times, ABI stability, hiding implementation
Curiously Recurring Template Pattern - static polymorphism
template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
};
class Derived : public Base<Derived> {
public:
void implementation() { /_ ... _/ }
};
Static polymorphism, mixin classes, compile-time polymorphism
Hide concrete types behind a uniform interface
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))) {}
};
std::function, std::any, runtime polymorphism without inheritance
Using raw pointers for ownership
Use std::unique_ptr or std::shared_ptr
Using new/delete directly
Use std::make_unique/std::make_shared
Using (Type)value casts
Use static_cast, dynamic_cast, const_cast, or reinterpret_cast
Using using namespace std; in headers
Use fully qualified names or limited using declarations in source files
Throwing exceptions in destructors
Mark destructors noexcept, handle errors internally
Using const_cast to remove const from data you do not own
Fix the design to avoid needing const_cast
Are you building a C++ project with dependencies and multiple targets?
Use CMake for cross-platform, modern build configuration
Use simple Makefile for single-file projects or prototypes
.
├── CMakeLists.txt
├── cmake/
│ └── modules/
├── src/
│ ├── CMakeLists.txt
│ ├── main.cpp
│ └── lib/
├── include/
│ └── project/
├── tests/
│ ├── CMakeLists.txt
│ └── test_*.cpp
└── build/
Target-based CMake (3.0+)
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)
Finding and using external dependencies
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)
Setting compiler warnings and options
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
>
)
Configure with Ninja generator
Build the project
Run tests
Build in Release mode
Install the project
LLVM C++ compiler
Enable C++20 standard
Use LLVM libc++ standard library
Enable comprehensive warnings
Treat warnings as errors
Enable sanitizers
GNU C++ compiler
Enable C++20 standard
Enable comprehensive warnings
Treat warnings as errors
Enable sanitizers
Enable static analysis (GCC 10+)
Static analysis and linting tool
clang-tidy src/*.cpp -- -std=c++20
.clang-tidy
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
Replace NULL with nullptr
Use auto where appropriate
Use override keyword
Convert C-style loops to range-based
Check ownership semantics
Detect use-after-move bugs
Detect unnecessary copies
Code formatting tool
clang-format -i src/*.cpp include/*.hpp
.clang-format
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
Runtime error detection tools
Detects memory errors (buffer overflow, use-after-free)
-fsanitize=address -fno-omit-frame-pointer
target_compile_options(myapp PRIVATE -fsanitize=address -fno-omit-frame-pointer)
target_link_options(myapp PRIVATE -fsanitize=address)
Detects undefined behavior (signed overflow, null dereference)
-fsanitize=undefined
target_compile_options(myapp PRIVATE -fsanitize=undefined)
target_link_options(myapp PRIVATE -fsanitize=undefined)
Detects data races and deadlocks
-fsanitize=thread
Cannot be combined with AddressSanitizer
Detects uninitialized memory reads (Clang only)
-fsanitize=memory
Requires all code and libraries to be instrumented
# CMakePresets.json sanitizer configuration
{
"configurePresets": [{
"name": "sanitize",
"cacheVariables": {
"CMAKE_CXX_FLAGS": "-fsanitize=address,undefined -fno-omit-frame-pointer"
}
}]
}
Do you need unit testing for C++ code?
Use GoogleTest for comprehensive testing features or Catch2 for header-only simplicity
Consider adding tests to improve code quality and maintainability
Google Test framework
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)
#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);
}
Catch2 test framework
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)
#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");
}
}
Use Context7 MCP for up-to-date C++ documentation
resolve-library-id libraryName="cppreference"
get-library-docs context7CompatibleLibraryID="/websites/cppreference_com" topic="std::unique_ptr"
get-library-docs context7CompatibleLibraryID="/Kitware/CMake" topic="target_link_libraries"
get-library-docs context7CompatibleLibraryID="/google/googletest" topic="assertions"
Use smart pointers instead of raw pointers for ownership
Enable -Wall -Wextra -Werror for all builds
Run clang-tidy before committing
Format with clang-format for consistent style
Prefer const correctness throughout
Use noexcept for move constructors and destructors
Prefer constexpr for compile-time computation
Use std::string_view for non-owning string references
Prefer range-based for loops over index-based
Use structured bindings for tuple/pair access
Document public API with Doxygen comments
Write unit tests alongside implementation
Understand C++ code requirements
1. Check CMakeLists.txt for build configuration
2. Review existing code patterns and standards
3. Identify memory management requirements
Write modern, safe C++ code
1. Use RAII and smart pointers
2. Follow C++ Core Guidelines
3. Prefer standard library over raw implementations
Verify C++ code correctness
1. Build with warnings enabled
2. Run static analysis tools
3. Execute tests with sanitizers
Compiler warning about unused variable
Fix warning, maintain clean build
Compilation error
Fix error, verify with full build
Memory leak or undefined behavior detected
Stop, require safe memory management
Buffer overflow or security vulnerability
Block operation, require immediate fix
Use smart pointers for memory management
Enable compiler warnings (-Wall -Wextra)
Follow C++ Core Guidelines
Raw pointers for ownership
Manual memory management when smart pointers suffice
Undefined behavior
Architecture design for C++ class hierarchies and template metaprogramming
Doxygen documentation and API reference generation
CMake configuration and C++ implementation tasks
Debugging memory leaks, segfaults, and undefined behavior
Symbol operations for C++ code navigation and refactoring
C++ documentation via /websites/cppreference_com and CMake docs via /Kitware/CMake
Debugging with sanitizers, valgrind, and gdb
Creating library documentation with Doxygen