Back to Skills

cpp-expert

majiayu000
Updated Today
1 views
58
9
58
View on GitHub
Othercppc++c++20c++23stltemplatesperformancememory

About

This Claude Skill provides expert-level C++ development assistance with modern C++20/23 features, STL, and performance optimization. Use it for guidance on memory management, templates, and high-performance programming patterns. It supports development workflows with tools like g++, clang++, CMake, and Make.

Quick Install

Claude Code

Recommended
Plugin CommandRecommended
/plugin add https://github.com/majiayu000/claude-skill-registry
Git CloneAlternative
git clone https://github.com/majiayu000/claude-skill-registry.git ~/.claude/skills/cpp-expert

Copy and paste this command in Claude Code to install this skill

Documentation

C++ Expert

Expert guidance for modern C++ development including C++20/23 features, STL, templates, memory management, and high-performance programming.

Core Concepts

Modern C++ Features (C++20/23)

  • Concepts and constraints
  • Ranges and views
  • Coroutines
  • Modules
  • Three-way comparison (spaceship operator)
  • std::format
  • std::span
  • Designated initializers
  • consteval and constinit

Memory Management

  • RAII (Resource Acquisition Is Initialization)
  • Smart pointers (unique_ptr, shared_ptr, weak_ptr)
  • Move semantics and perfect forwarding
  • Memory allocation strategies
  • Custom allocators
  • Memory pools

Performance

  • Zero-cost abstractions
  • Inline optimization
  • Template metaprogramming
  • Compile-time computation (constexpr)
  • Cache-friendly data structures
  • SIMD operations

Modern C++ Syntax

Concepts (C++20)

#include <concepts>
#include <iostream>
#include <vector>

// Define concepts
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;

template<typename T>
concept Printable = requires(T t, std::ostream& os) {
    { os << t } -> std::same_as<std::ostream&>;
};

// Use concepts
template<Numeric T>
T add(T a, T b) {
    return a + b;
}

template<Printable T>
void print(const T& value) {
    std::cout << value << '\n';
}

// Concept with multiple requirements
template<typename T>
concept Container = requires(T container) {
    typename T::value_type;
    { container.begin() } -> std::same_as<typename T::iterator>;
    { container.end() } -> std::same_as<typename T::iterator>;
    { container.size() } -> std::convertible_to<std::size_t>;
};

template<Container C>
void process(const C& container) {
    for (const auto& item : container) {
        std::cout << item << ' ';
    }
}

Ranges and Views (C++20)

#include <ranges>
#include <vector>
#include <algorithm>

// Ranges
std::vector<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// Filter and transform with views
auto even_squares = numbers
    | std::views::filter([](int n) { return n % 2 == 0; })
    | std::views::transform([](int n) { return n * n; });

for (int value : even_squares) {
    std::cout << value << ' '; // 4 16 36 64 100
}

// Take first N elements
auto first_three = numbers | std::views::take(3);

// Drop first N elements
auto skip_two = numbers | std::views::drop(2);

// Reverse
auto reversed = numbers | std::views::reverse;

// Join multiple ranges
std::vector<std::vector<int>> nested = {{1, 2}, {3, 4}, {5, 6}};
auto flattened = nested | std::views::join;

// Split string
std::string text = "one,two,three";
auto words = text | std::views::split(',');

// Lazy evaluation - nothing computed yet
auto lazy = numbers
    | std::views::filter([](int n) { return n > 5; })
    | std::views::transform([](int n) { return n * 2; })
    | std::views::take(3);

// Computation happens here
std::vector<int> result(lazy.begin(), lazy.end()); // {12, 14, 16}

Coroutines (C++20)

#include <coroutine>
#include <iostream>
#include <stdexcept>

// Generator coroutine
template<typename T>
class Generator {
public:
    struct promise_type {
        T current_value;

        auto get_return_object() {
            return Generator{std::coroutine_handle<promise_type>::from_promise(*this)};
        }

        auto initial_suspend() { return std::suspend_always{}; }
        auto final_suspend() noexcept { return std::suspend_always{}; }

        auto yield_value(T value) {
            current_value = value;
            return std::suspend_always{};
        }

        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };

    explicit Generator(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~Generator() { if (handle) handle.destroy(); }

    bool next() {
        handle.resume();
        return !handle.done();
    }

    T value() const {
        return handle.promise().current_value;
    }

private:
    std::coroutine_handle<promise_type> handle;
};

// Use generator
Generator<int> fibonacci() {
    int a = 0, b = 1;
    while (true) {
        co_yield a;
        auto next = a + b;
        a = b;
        b = next;
    }
}

int main() {
    auto fib = fibonacci();
    for (int i = 0; i < 10; ++i) {
        fib.next();
        std::cout << fib.value() << ' '; // 0 1 1 2 3 5 8 13 21 34
    }
}

Smart Pointers

#include <memory>
#include <vector>

class Resource {
    int* data;
public:
    Resource(int size) : data(new int[size]) {
        std::cout << "Resource acquired\n";
    }

    ~Resource() {
        delete[] data;
        std::cout << "Resource released\n";
    }
};

// unique_ptr - exclusive ownership
std::unique_ptr<Resource> create_resource() {
    return std::make_unique<Resource>(100);
}

auto resource = create_resource();
// resource.reset(); // Manually release
// auto copy = resource; // Error: cannot copy unique_ptr
auto moved = std::move(resource); // Transfer ownership

// shared_ptr - shared ownership
std::shared_ptr<Resource> shared = std::make_shared<Resource>(100);
{
    std::shared_ptr<Resource> shared2 = shared; // Reference count = 2
    std::cout << "Use count: " << shared.use_count() << '\n'; // 2
} // shared2 destroyed, ref count = 1
// shared destroyed, Resource released

// weak_ptr - non-owning reference
std::weak_ptr<Resource> weak = shared;
if (auto locked = weak.lock()) {
    // Use resource
}

// Custom deleter
auto file_deleter = [](FILE* f) { if (f) fclose(f); };
std::unique_ptr<FILE, decltype(file_deleter)> file(
    fopen("data.txt", "r"),
    file_deleter
);

Move Semantics

#include <utility>
#include <vector>

class Buffer {
    int* data;
    size_t size;

public:
    // Constructor
    Buffer(size_t s) : size(s), data(new int[s]) {
        std::cout << "Constructor\n";
    }

    // Destructor
    ~Buffer() {
        delete[] data;
        std::cout << "Destructor\n";
    }

    // Copy constructor
    Buffer(const Buffer& other) : size(other.size), data(new int[other.size]) {
        std::copy(other.data, other.data + size, data);
        std::cout << "Copy constructor\n";
    }

    // Move constructor
    Buffer(Buffer&& other) noexcept : size(other.size), data(other.data) {
        other.data = nullptr;
        other.size = 0;
        std::cout << "Move constructor\n";
    }

    // Copy assignment
    Buffer& operator=(const Buffer& other) {
        if (this != &other) {
            delete[] data;
            size = other.size;
            data = new int[size];
            std::copy(other.data, other.data + size, data);
            std::cout << "Copy assignment\n";
        }
        return *this;
    }

    // Move assignment
    Buffer& operator=(Buffer&& other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data;
            size = other.size;
            other.data = nullptr;
            other.size = 0;
            std::cout << "Move assignment\n";
        }
        return *this;
    }
};

// Perfect forwarding
template<typename T, typename... Args>
std::unique_ptr<T> make_unique_custom(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

Templates and Metaprogramming

#include <type_traits>
#include <iostream>

// Function template
template<typename T>
T max(T a, T b) {
    return (a > b) ? a : b;
}

// Class template
template<typename T, size_t N>
class Array {
    T data[N];

public:
    constexpr size_t size() const { return N; }

    T& operator[](size_t index) { return data[index]; }
    const T& operator[](size_t index) const { return data[index]; }
};

// Variadic templates
template<typename... Args>
void print(Args... args) {
    ((std::cout << args << ' '), ...); // Fold expression (C++17)
    std::cout << '\n';
}

// SFINAE (Substitution Failure Is Not An Error)
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
abs(T value) {
    return value < 0 ? -value : value;
}

template<typename T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type
abs(T value) {
    return std::fabs(value);
}

// Type traits
template<typename T>
void check_type() {
    std::cout << std::boolalpha;
    std::cout << "is_integral: " << std::is_integral_v<T> << '\n';
    std::cout << "is_floating_point: " << std::is_floating_point_v<T> << '\n';
    std::cout << "is_pointer: " << std::is_pointer_v<T> << '\n';
}

// Compile-time computation
constexpr int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

constexpr int fact10 = factorial(10); // Computed at compile time

std::format (C++20)

#include <format>
#include <iostream>

int main() {
    int age = 30;
    std::string name = "Alice";

    // Basic formatting
    std::cout << std::format("Hello, {}!", name) << '\n';

    // Positional arguments
    std::cout << std::format("{1} is {0} years old", age, name) << '\n';

    // Format specifiers
    double pi = 3.14159265359;
    std::cout << std::format("Pi: {:.2f}", pi) << '\n'; // 3.14

    // Width and alignment
    std::cout << std::format("{:<10} {:>10}", "left", "right") << '\n';

    // Numbers
    int num = 42;
    std::cout << std::format("Dec: {0:d}, Hex: {0:x}, Bin: {0:b}", num) << '\n';

    // Padding
    std::cout << std::format("{:0>5}", num) << '\n'; // 00042

    return 0;
}

STL Containers

Sequential Containers

#include <vector>
#include <deque>
#include <list>
#include <array>

// vector - dynamic array
std::vector<int> vec = {1, 2, 3, 4, 5};
vec.push_back(6);
vec.emplace_back(7); // Construct in-place
vec.reserve(100); // Pre-allocate capacity

// deque - double-ended queue
std::deque<int> deq = {1, 2, 3};
deq.push_front(0);
deq.push_back(4);

// list - doubly-linked list
std::list<int> lst = {1, 2, 3};
lst.push_front(0);
lst.push_back(4);
lst.remove(2); // Remove all elements with value 2

// array - fixed-size array
std::array<int, 5> arr = {1, 2, 3, 4, 5};

Associative Containers

#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>

// map - ordered key-value pairs
std::map<std::string, int> ages;
ages["Alice"] = 30;
ages["Bob"] = 25;
ages.insert({"Charlie", 35});

// set - ordered unique elements
std::set<int> numbers = {3, 1, 4, 1, 5, 9};
numbers.insert(2);

// unordered_map - hash table
std::unordered_map<std::string, int> hash_map;
hash_map["key"] = 42;

// unordered_set - hash set
std::unordered_set<int> hash_set = {1, 2, 3};

Algorithms

#include <algorithm>
#include <numeric>
#include <vector>

std::vector<int> numbers = {5, 2, 8, 1, 9, 3, 7};

// Sorting
std::sort(numbers.begin(), numbers.end());
std::sort(numbers.begin(), numbers.end(), std::greater<int>());

// Searching
auto it = std::find(numbers.begin(), numbers.end(), 8);
bool found = std::binary_search(numbers.begin(), numbers.end(), 5);

// Transforming
std::vector<int> doubled(numbers.size());
std::transform(numbers.begin(), numbers.end(), doubled.begin(),
    [](int n) { return n * 2; });

// Filtering
std::vector<int> evens;
std::copy_if(numbers.begin(), numbers.end(), std::back_inserter(evens),
    [](int n) { return n % 2 == 0; });

// Accumulate
int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
int product = std::accumulate(numbers.begin(), numbers.end(), 1,
    std::multiplies<int>());

// Partition
auto pivot = std::partition(numbers.begin(), numbers.end(),
    [](int n) { return n < 5; });

// Remove
numbers.erase(std::remove(numbers.begin(), numbers.end(), 5), numbers.end());

// Unique (remove consecutive duplicates)
std::sort(numbers.begin(), numbers.end());
numbers.erase(std::unique(numbers.begin(), numbers.end()), numbers.end());

Concurrency

#include <thread>
#include <mutex>
#include <future>
#include <atomic>

// Thread
void worker(int id) {
    std::cout << "Thread " << id << '\n';
}

std::thread t1(worker, 1);
std::thread t2(worker, 2);
t1.join();
t2.join();

// Mutex
std::mutex mtx;
int shared_data = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    ++shared_data;
}

// Atomic
std::atomic<int> counter{0};
counter++; // Thread-safe
counter.fetch_add(5);

// Future and promise
std::promise<int> prom;
std::future<int> fut = prom.get_future();

std::thread t([&prom]() {
    std::this_thread::sleep_for(std::chrono::seconds(1));
    prom.set_value(42);
});

int result = fut.get(); // Blocks until ready
t.join();

// async
auto future = std::async(std::launch::async, []() {
    return 42;
});

int value = future.get();

Build Systems

CMake

# CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(MyApp VERSION 1.0.0 LANGUAGES CXX)

# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Compiler flags
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    add_compile_options(-Wall -Wextra -Wpedantic -O3)
endif()

# Find packages
find_package(Threads REQUIRED)
find_package(Boost 1.75 REQUIRED COMPONENTS system filesystem)

# Add executable
add_executable(myapp
    src/main.cpp
    src/module.cpp
    include/module.h
)

# Include directories
target_include_directories(myapp PRIVATE include)

# Link libraries
target_link_libraries(myapp PRIVATE
    Threads::Threads
    Boost::system
    Boost::filesystem
)

# Install
install(TARGETS myapp DESTINATION bin)

Best Practices

RAII

// ❌ Bad: Manual resource management
void process_file() {
    FILE* f = fopen("data.txt", "r");
    // ... work with file
    fclose(f); // Easy to forget
}

// ✅ Good: RAII with smart pointers
void process_file() {
    auto file = std::unique_ptr<FILE, decltype(&fclose)>(
        fopen("data.txt", "r"),
        &fclose
    );
    // ... work with file
    // Automatically closed when leaving scope
}

Const Correctness

class Data {
    int value;

public:
    // Const method
    int get_value() const { return value; }

    // Non-const method
    void set_value(int v) { value = v; }
};

// Const reference parameter
void process(const Data& data) {
    int v = data.get_value(); // OK
    // data.set_value(42); // Error: cannot modify const object
}

Rule of Zero/Three/Five

  • Rule of Zero: If you don't manage resources, don't declare special members
  • Rule of Three: If you declare destructor, copy constructor, or copy assignment, declare all three
  • Rule of Five: Add move constructor and move assignment

Anti-Patterns to Avoid

Raw pointers for ownership: Use smart pointers ❌ Manual memory management: Use RAII ❌ Using C-style arrays: Use std::array or std::vector ❌ Ignoring const correctness: Mark everything const that can be ❌ Unnecessary copies: Use move semantics and references ❌ Premature optimization: Profile before optimizing ❌ Using new without delete: Use smart pointers

Resources

GitHub Repository

majiayu000/claude-skill-registry
Path: skills/cpp-expert

Related Skills

when-creating-skill-template-use-skill-builder

Other

This Claude Skill helps developers create new Claude Code Skills with proper YAML frontmatter and directory structure. It generates all required files including documentation and ensures skills follow best practices. Use this template generator when building reusable skills to maintain specification compliance and progressive disclosure.

View skill

performance-analysis

Other

This skill provides comprehensive performance analysis for Claude Flow swarms, detecting bottlenecks and profiling operations. It generates detailed reports and offers AI-powered optimization recommendations to improve swarm performance. Use it when you need to monitor, analyze, and optimize the efficiency of your Claude Flow implementations.

View skill

when-profiling-performance-use-performance-profiler

Other

This performance profiling skill helps developers identify and optimize application bottlenecks across CPU, memory, I/O, and network dimensions. It provides comprehensive analysis through baseline measurement, bottleneck detection, and root cause investigation phases. Use this skill when you need systematic performance optimization with tools like perf, Instruments, or clinic.js integration.

View skill

performance-analysis

Other

This skill provides comprehensive performance analysis and bottleneck detection for Claude Flow swarms. It identifies issues across communication, processing, memory, and network layers while offering AI-powered optimization recommendations. Use it for real-time monitoring, profiling swarm operations, and generating detailed performance reports.

View skill