C++20 Programming Skill
When writing C++ code, follow these guidelines. Target C++20 as the language standard.
File Conventions
- Header files use the
.hpp extension.
- Source files use the
.cpp extension.
- Every
.hpp must have a corresponding .cpp file, even if it would otherwise be empty. This ensures the header compiles independently and provides a place for future implementation.
- All headers use
#pragma once as the include guard.
- Use the
.clang-format file in this repository for all formatting. Run clang-format before committing.
Naming Conventions
Follow Rust-style capitalization applied to C++:
| Element |
Convention |
Example |
| Classes, structs, enums |
UpperCamelCase |
HttpRequest, FileReader |
| Enum variants (scoped enums) |
UpperCamelCase |
Success, NotFound |
| Functions, methods |
snake_case |
read_file(), is_empty() |
| Variables, parameters |
snake_case |
line_count, buffer_size |
Constants, constexpr values |
SCREAMING_SNAKE_CASE |
MAX_SIZE, DEFAULT_PORT |
| Namespaces |
snake_case |
my_project, io |
| Template parameters |
UpperCamelCase |
T, Value, Allocator |
| Macros (avoid when possible) |
SCREAMING_SNAKE_CASE |
DEBUG_LOG |
Acronyms in UpperCamelCase names are treated as a single word: Http, Xml, Uuid — not HTTP, XML, UUID.
Predicate functions use prefixes like is_, has_, should_.
Formatting
All formatting is enforced by the .clang-format file in this repository. Key rules:
- Indentation: 4 spaces, no tabs.
- Braces: Opening brace on the same line (Attach/K&R style).
- Line length: 100 characters maximum.
- Indent style: Block indent, not visual indent.
- Arguments: One argument per line when wrapping is required.
- Namespaces: Do not indent namespace contents.
- Access modifiers: Outdented by one level (
public: at column 0 inside class body).
- No spaces inside parentheses or angle brackets.
C++ Core Guidelines
Follow the C++ Core Guidelines. Key principles:
Resource Management
- Use RAII for all resource management. Resources are tied to object lifetimes.
- Use
std::unique_ptr for exclusive ownership and std::shared_ptr for shared ownership.
- No owning raw pointers. Raw pointers may only be used as non-owning observers.
- No
malloc/free. Use standard containers and smart pointers.
Type Safety
- No C-style casts. Use
static_cast, dynamic_cast, const_cast, or reinterpret_cast (sparingly).
- No raw C arrays. Use
std::array, std::vector, or std::span.
- Use
std::span<T> instead of (pointer, count) pairs at interface boundaries.
- Use scoped enums (
enum class) instead of unscoped enums.
Modern C++20 Features
- Use concepts to constrain templates instead of SFINAE or unconstrained templates.
- Use range-for loops and ranges over index-based iteration.
- Use structured bindings to unpack pairs, tuples, and structs.
- Use
std::optional for values that may be absent and std::variant for type-safe unions.
- Use
std::format for string formatting instead of string concatenation or streams.
- Use
constexpr and consteval wherever possible for compile-time computation.
Error Handling
- Prefer exceptions for error handling. Errors must not be silently ignored.
- Use RAII to ensure exception safety — destructors handle cleanup.
Interfaces
- Keep function parameter lists short (fewer than four parameters).
- Avoid adjacent parameters of the same type that could be accidentally swapped.
- Use
override and final explicitly on virtual functions.
- Prefer returning values over out-parameters.
Sean Parent's Better Code Principles
Follow the principles from Sean Parent's Better Code series:
No Raw Loops
- Prefer algorithms from
<algorithm> and C++20 ranges over hand-written loops.
- If a lambda is more than a simple composition of two functions, give it a name.
- A raw loop is acceptable when an algorithm would obscure intent — add a comment explaining why.
No Raw Pointers
- Default to value semantics. Objects should behave like values: assignment copies, equality compares content.
- Use smart pointers only when ownership semantics require them.
shared_ptr should not appear in interfaces — it is an implementation detail.
No Raw Synchronization Primitives
- Do not use raw mutexes, locks, condition variables, or atomics directly.
- Use higher-level abstractions: task systems, futures with continuations, parallel algorithms.
Design Principles
- Value semantics over reference semantics: values are easier to reason about locally.
- Concept-based polymorphism: prefer type erasure and concepts over deep inheritance hierarchies.
- Composition over inheritance: favor composing small, focused types.
- Local reasoning: design code so correctness can be verified without understanding the entire codebase.
- Copy-on-write: use it to give value semantics to types that would otherwise be expensive to copy.
1---2name: claude-skill-cpp3description: C++20 coding guidelines and conventions. Use when writing, reviewing, or refactoring C++ code. Covers naming, formatting, resource management, type safety, modern C++20 features, and design principles from the C++ Core Guidelines and Sean Parent's Better Code series.4---56# C++20 Programming Skill78When writing C++ code, follow these guidelines. Target **C++20** as the language standard.910## File Conventions1112- Header files use the `.hpp` extension.13- Source files use the `.cpp` extension.14- Every `.hpp` must have a corresponding `.cpp` file, even if it would otherwise be empty. This ensures the header compiles independently and provides a place for future implementation.15- All headers use `#pragma once` as the include guard.16- Use the `.clang-format` file in this repository for all formatting. Run `clang-format` before committing.1718## Naming Conventions1920Follow Rust-style capitalization applied to C++:2122| Element | Convention | Example |23|---|---|---|24| Classes, structs, enums | `UpperCamelCase` | `HttpRequest`, `FileReader` |25| Enum variants (scoped enums) | `UpperCamelCase` | `Success`, `NotFound` |26| Functions, methods | `snake_case` | `read_file()`, `is_empty()` |27| Variables, parameters | `snake_case` | `line_count`, `buffer_size` |28| Constants, `constexpr` values | `SCREAMING_SNAKE_CASE` | `MAX_SIZE`, `DEFAULT_PORT` |29| Namespaces | `snake_case` | `my_project`, `io` |30| Template parameters | `UpperCamelCase` | `T`, `Value`, `Allocator` |31| Macros (avoid when possible) | `SCREAMING_SNAKE_CASE` | `DEBUG_LOG` |3233Acronyms in `UpperCamelCase` names are treated as a single word: `Http`, `Xml`, `Uuid` — not `HTTP`, `XML`, `UUID`.3435Predicate functions use prefixes like `is_`, `has_`, `should_`.3637## Formatting3839All formatting is enforced by the `.clang-format` file in this repository. Key rules:4041- **Indentation**: 4 spaces, no tabs.42- **Braces**: Opening brace on the same line (Attach/K&R style).43- **Line length**: 100 characters maximum.44- **Indent style**: Block indent, not visual indent.45- **Arguments**: One argument per line when wrapping is required.46- **Namespaces**: Do not indent namespace contents.47- **Access modifiers**: Outdented by one level (`public:` at column 0 inside class body).48- No spaces inside parentheses or angle brackets.4950## C++ Core Guidelines5152Follow the [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines). Key principles:5354### Resource Management55- Use RAII for all resource management. Resources are tied to object lifetimes.56- Use `std::unique_ptr` for exclusive ownership and `std::shared_ptr` for shared ownership.57- No owning raw pointers. Raw pointers may only be used as non-owning observers.58- No `malloc`/`free`. Use standard containers and smart pointers.5960### Type Safety61- No C-style casts. Use `static_cast`, `dynamic_cast`, `const_cast`, or `reinterpret_cast` (sparingly).62- No raw C arrays. Use `std::array`, `std::vector`, or `std::span`.63- Use `std::span<T>` instead of `(pointer, count)` pairs at interface boundaries.64- Use scoped enums (`enum class`) instead of unscoped enums.6566### Modern C++20 Features67- Use **concepts** to constrain templates instead of SFINAE or unconstrained templates.68- Use **range-for loops** and **ranges** over index-based iteration.69- Use **structured bindings** to unpack pairs, tuples, and structs.70- Use `std::optional` for values that may be absent and `std::variant` for type-safe unions.71- Use `std::format` for string formatting instead of string concatenation or streams.72- Use `constexpr` and `consteval` wherever possible for compile-time computation.7374### Error Handling75- Prefer exceptions for error handling. Errors must not be silently ignored.76- Use RAII to ensure exception safety — destructors handle cleanup.7778### Interfaces79- Keep function parameter lists short (fewer than four parameters).80- Avoid adjacent parameters of the same type that could be accidentally swapped.81- Use `override` and `final` explicitly on virtual functions.82- Prefer returning values over out-parameters.8384## Sean Parent's Better Code Principles8586Follow the principles from Sean Parent's [Better Code](https://sean-parent.stlab.cc/papers-and-presentations/) series:8788### No Raw Loops89- Prefer algorithms from `<algorithm>` and C++20 ranges over hand-written loops.90- If a lambda is more than a simple composition of two functions, give it a name.91- A raw loop is acceptable when an algorithm would obscure intent — add a comment explaining why.9293### No Raw Pointers94- Default to **value semantics**. Objects should behave like values: assignment copies, equality compares content.95- Use smart pointers only when ownership semantics require them.96- `shared_ptr` should not appear in interfaces — it is an implementation detail.9798### No Raw Synchronization Primitives99- Do not use raw mutexes, locks, condition variables, or atomics directly.100- Use higher-level abstractions: task systems, futures with continuations, parallel algorithms.101102### Design Principles103- **Value semantics over reference semantics**: values are easier to reason about locally.104- **Concept-based polymorphism**: prefer type erasure and concepts over deep inheritance hierarchies.105- **Composition over inheritance**: favor composing small, focused types.106- **Local reasoning**: design code so correctness can be verified without understanding the entire codebase.107- **Copy-on-write**: use it to give value semantics to types that would otherwise be expensive to copy.