$npx -y skills add softspark/ai-toolkit --skill cpp-rulesC++ coding rules: style, patterns, security, testing. Triggers: .cpp, .cc, .cxx, .hpp, .h, CMakeLists.txt, Makefile, GoogleTest, clang-tidy.
| 1 | # C++ Rules |
| 2 | |
| 3 | These rules come from `app/rules/cpp/` in ai-toolkit. They cover |
| 4 | the project's standards for coding style, frameworks, patterns, |
| 5 | security, and testing in C++. Apply them when writing or |
| 6 | reviewing C++ code. |
| 7 | |
| 8 | # C++ Coding Style |
| 9 | |
| 10 | ## Naming |
| 11 | - PascalCase: classes, structs, enums, type aliases, concepts. |
| 12 | - camelCase or snake_case: functions, methods, variables (be consistent per project). |
| 13 | - UPPER_SNAKE: macros, compile-time constants. |
| 14 | - Prefix member variables with `m_` or suffix with `_` (pick one convention). |
| 15 | - Namespace names: lowercase, short (`namespace io`, `namespace util`). |
| 16 | |
| 17 | ## Modern C++ (17/20/23) |
| 18 | - Use `auto` for iterator types and complex template deductions. |
| 19 | - Use `std::optional<T>` instead of sentinel values or pointers for optional returns. |
| 20 | - Use `std::variant` over union types. Use `std::visit` for dispatch. |
| 21 | - Use `std::string_view` for non-owning string parameters. |
| 22 | - Use structured bindings: `auto [key, value] = *map.begin();`. |
| 23 | - Use `constexpr` for compile-time evaluation. Prefer over macros. |
| 24 | |
| 25 | ## Memory Management |
| 26 | - Use RAII exclusively. Every resource acquisition is an initialization. |
| 27 | - Use `std::unique_ptr` for exclusive ownership (default choice). |
| 28 | - Use `std::shared_ptr` only when ownership is genuinely shared. |
| 29 | - Never use raw `new`/`delete`. Use `std::make_unique` / `std::make_shared`. |
| 30 | - Use `std::span<T>` (C++20) for non-owning views over contiguous data. |
| 31 | |
| 32 | ## Functions |
| 33 | - Pass small types by value. Pass large types by `const&`. |
| 34 | - Use `[[nodiscard]]` on functions whose return value must not be ignored. |
| 35 | - Use `noexcept` on functions that do not throw (move constructors, destructors). |
| 36 | - Limit function parameters to 4. Use structs for configuration objects. |
| 37 | - Use trailing return types for complex template return deductions. |
| 38 | |
| 39 | ## Includes and Dependencies |
| 40 | - Use `#pragma once` or include guards. Prefer `#pragma once` for simplicity. |
| 41 | - Order: corresponding header, C++ stdlib, third-party, project headers. |
| 42 | - Forward-declare in headers when possible to reduce compile times. |
| 43 | - Minimize header dependencies. Use the Pimpl idiom for ABI stability. |
| 44 | |
| 45 | ## Avoid |
| 46 | - Raw pointers for ownership. Use smart pointers. |
| 47 | - C-style casts. Use `static_cast`, `dynamic_cast`, `const_cast`. |
| 48 | - Macros for constants or functions. Use `constexpr` and templates. |
| 49 | - `using namespace std;` in headers. Acceptable in .cpp files with caution. |
| 50 | - `std::endl` -- use `'\n'` (endl flushes the buffer unnecessarily). |
| 51 | |
| 52 | ## Formatting |
| 53 | - Use clang-format with a committed `.clang-format` file. |
| 54 | - Use clang-tidy for static analysis and automated modernization. |
| 55 | - Max line length: 100-120 characters. |
| 56 | - Braces: use Allman or K&R consistently per project. |
| 57 | |
| 58 | # C++ Frameworks |
| 59 | |
| 60 | ## CMake |
| 61 | - Use modern CMake (3.14+): target-based, not directory-based. |
| 62 | - Use `target_link_libraries` with `PUBLIC`/`PRIVATE`/`INTERFACE` visibility. |
| 63 | - Use `FetchContent` for dependency management. Avoid manual submodule vendoring. |
| 64 | - Set `CMAKE_CXX_STANDARD 20` (or 23) at the project level. |
| 65 | - Use `target_compile_options` for per-target flags, not global `add_compile_options`. |
| 66 | - Export targets with `install(TARGETS ... EXPORT ...)` for library consumers. |
| 67 | |
| 68 | ## Boost |
| 69 | - Use Boost.Asio for async networking and I/O. |
| 70 | - Use `boost::beast` for HTTP/WebSocket built on Asio. |
| 71 | - Use `boost::json` or `nlohmann/json` for JSON parsing. |
| 72 | - Prefer C++ stdlib equivalents when available (e.g., `std::optional` over `boost::optional`). |
| 73 | - Link only the Boost libraries you actually use. Many are header-only. |
| 74 | |
| 75 | ## Qt |
| 76 | - Use signals and slots for event-driven communication. |
| 77 | - Use `QObject` parent-child ownership for automatic memory management. |
| 78 | - Use `QML` for declarative UI. Keep business logic in C++ backend. |
| 79 | - Use `QThread` with worker objects (moveToThread), not subclassing QThread. |
| 80 | - Use smart pointers for non-QObject resources. QObject children are auto-deleted. |
| 81 | |
| 82 | ## gRPC |
| 83 | - Define services in `.proto` files. Generate C++ stubs with `protoc`. |
| 84 | - Use async server with `CompletionQueue` for high-throughput services. |
| 85 | - Use `grpc::ClientContext` for per-call deadlines and metadata. |
| 86 | - Use interceptors for logging, auth, and metrics. |
| 87 | - Set deadlines on every RPC call to prevent hanging. |
| 88 | |
| 89 | ## Networking (Asio) |
| 90 | - Use `io_context` as the event loop. Run from one or more threads. |
| 91 | - Use `co_await` (C++20 coroutines) with Asio for clean async code. |
| 92 | - Use `strand` for serializing access to shared state across handlers. |
| 93 | - Use `steady_timer` for timeouts and periodic tasks. |
| 94 | - Handle errors via `error_code` parameter, not exceptions, in async callbacks. |
| 95 | |
| 96 | ## Database |
| 97 | - Use `libpq` (PostgreSQL) or `SOCI` for database access. |
| 98 | - Use prepared statements exclusively. Never concatenate SQL strings. |
| 99 | - Use connection pooling for multi-threaded server applications. |
| 100 | - Use `SQLite` via `sqlit |