Back to skills
SKILL.md
Cpp Coding Standards
ASecurityProduction-ready C/C++ coding standards enforcing safety, modern patterns, and maintainability. Use when enforcing cpp coding conventions and style rules.
- 9 stars
- 0 votes
- 0 copies
- 9 views
- Added September 8, 2026
Security analysis
100/100npx -y skills add anubhavg-icpl/vibe --skill cpp-coding-standards --agent claude-codeAre you the author of Cpp Coding Standards?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-cpp-coding-standards)---
name: cpp-coding-standards
description: Production-ready C/C++ coding standards enforcing safety, modern patterns, and maintainability. Use when enforcing cpp coding conventions and style rules.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: coding-standards
tags: [cpp, c, coding-standards, modern-cpp, clang-tidy]
---
# C/C++ Coding Standards Mode
You are a C/C++ code quality expert. Your role is to enforce modern C++ patterns, memory safety, and production-ready code following industry standards and the C++ Core Guidelines.
## Core Principles
1. **Safety First** - Prevent undefined behavior
2. **RAII** - Resource Acquisition Is Initialization
3. **Zero-Cost Abstractions** - High-level without runtime overhead
4. **Modern C++** - Use C++17/20/23 features
## Naming Conventions
### Types and Classes
```cpp
// ✅ PascalCase for types, classes, structs, enums
class UserService;
struct Point;
enum class Color { Red, Green, Blue };
using UserId = std::string;
// ✅ Descriptive names
class HttpRequestHandler;
class DatabaseConnectionPool;
// ✅ Template parameters
template<typename T> // Single type
template<typename Key, typename Value> // Multiple types
template<typename Container> // Descriptive when complex
```
### Functions and Variables
```cpp
// ✅ snake_case for functions and variables (Google/LLVM style)
void calculate_total();
int item_count;
std::string user_name;
// OR camelCase (Microsoft/some game engines)
void calculateTotal();
int itemCount;
std::string userName;
// ✅ Constants and constexpr
constexpr int kMaxConnections = 100; // k prefix (Google style)
constexpr int MAX_CONNECTIONS = 100; // SCREAMING_CASE
static constexpr auto DefaultTimeout = std::chrono::seconds{30};
// ✅ Member variables
class User {
private:
std::string name_; // Trailing underscore (Google)
std::string m_name; // m_ prefix (Microsoft)
int id_;
};
// ✅ Boolean variables/functions
bool is_active;
bool has_permission;
bool can_access();
bool should_retry();
```
### Namespaces and Macros
```cpp
// ✅ lowercase for namespaces
namespace mycompany::project::utils {
// ...
}
// ✅ SCREAMING_SNAKE_CASE for macros (avoid macros when possible)
#define MAX_BUFFER_SIZE 1024
#define MYPROJECT_DEBUG_LOG(msg) // Project prefix
// ❌ Avoid macros - use constexpr, inline, or templates
#define SQUARE(x) ((x) * (x)) // ❌ Macro
template<typename T>
constexpr T square(T x) { return x * x; } // ✅ Template
```
## Modern C++ Features
### Smart Pointers
```cpp
// ✅ Use unique_ptr for exclusive ownership
auto user = std::make_unique<User>("Alice");
void transfer_ownership(std::unique_ptr<User> user);
// ✅ Use shared_ptr for shared ownership
auto shared_resource = std::make_shared<Resource>();
void share_resource(std::shared_ptr<Resource> resource);
// ✅ Use weak_ptr to break cycles
class Node {
std::shared_ptr<Node> next;
std::weak_ptr<Node> parent; // Prevent cycle
};
// ❌ Never use raw new/delete
User* user = new User(); // ❌
delete user; // ❌
// ✅ Use raw pointers only for non-owning references
void process(const User* user); // Observer, doesn't own
void process(User& user); // Better: reference
```
### RAII and Scope Guards
```cpp
// ✅ RAII for resource management
class FileHandle {
public:
explicit FileHandle(const std::string& path)
: handle_(std::fopen(path.c_str(), "r")) {
if (!handle_) {
throw std::runtime_error("Failed to open file");
}
}
~FileHandle() {
if (handle_) std::fclose(handle_);
}
// Non-copyable
FileHandle(const FileHandle&) = delete;
FileHandle& operator=(const FileHandle&) = delete;
// Movable
FileHandle(FileHandle&& other) noexcept : handle_(other.handle_) {
other.handle_ = nullptr;
}
private:
FILE* handle_;
};
// ✅ Use lock_guard for mutex
void update_data() {
std::lock_guard<std::mutex> lock(mutex_);
// Automatically unlocks when scope exits
data_.push_back(item);
}
// ✅ Use scoped_lock for multiple mutexes
void transfer(Account& from, Account& to, int amount) {
std::scoped_lock lock(from.mutex_, to.mutex_);
from.balance -= amount;
to.balance += amount;
}
```
### Move Semantics
```cpp
// ✅ Implement move operations
class Buffer {
public:
Buffer(size_t size) : data_(new char[size]), size_(size) {}
// Move constructor
Buffer(Buffer&& other) noexcept
: data_(other.data_), size_(other.size_) {
other.data_ = nullptr;
other.size_ = 0;
}
// Move assignment
Buffer& operator=(Buffer&& other) noexcept {
if (this != &other) {
delete[] data_;
data_ = other.data_;
size_ = other.size_;
other.data_ = nullptr;
other.size_ = 0;
}
return *this;
}
~Buffer() { delete[] data_; }
private:
char* data_;
size_t size_;
};
// ✅ Use std::move to transfer ownership
std::vector<Buffer> buffers;
Buffer buf(1024);
buffers.push_back(std::move(buf)); // Move, not copy
// ✅ Return by value (RVO/NRVO applies)
std::vector<int> create_vector() {
std::vector<int> result;
// ... fill result
return result; // Move or RVO
}
```
### Optional and Variant
```cpp
// ✅ Use std::optional for potentially absent values
std::optional<User> find_user(const std::string& id) {
auto it = users_.find(id);
if (it != users_.end()) {
return it->second;
}
return std::nullopt;
}
// ✅ Handle optional values
if (auto user = find_user("123")) {
std::cout << user->name << '\n';
}
auto name = find_user("123")
.transform([](const User& u) { return u.name; })
.value_or("Unknown");
// ✅ Use std::variant for type-safe unions
using Result = std::variant<Success, Error>;
Result process() {
if (success) {
return Success{data};
}
return Error{"failed"};
}
// ✅ Visit variants
std::visit(overloaded{
[](const Success& s) { handle_success(s); },
[](const Error& e) { handle_error(e); }
}, result);
```
### Concepts (C++20)
```cpp
// ✅ Define concepts for constraints
template<typename T>
concept Numeric = std::integral<T> || std::floating_point<T>;
template<typename T>
concept Container = requires(T c) {
{ c.begin() } -> std::input_iterator;
{ c.end() } -> std::input_iterator;
{ c.size() } -> std::convertible_to<std::size_t>;
};
// ✅ Use concepts in templates
template<Numeric T>
T add(T a, T b) { return a + b; }
template<Container C>
void print_all(const C& container) {
for (const auto& item : container) {
std::cout << item << '\n';
}
}
// ✅ Requires clause for complex constraints
template<typename T>
requires std::copyable<T> && std::default_initializable<T>
class Cache {
// ...
};
```
### Ranges (C++20)
```cpp
// ✅ Use ranges for cleaner algorithms
#include <ranges>
auto active_names = users
| std::views::filter([](const User& u) { return u.is_active; })
| std::views::transform([](const User& u) { return u.name; })
| std::views::take(10);
for (const auto& name : active_names) {
std::cout << name << '\n';
}
// ✅ Range algorithms
auto it = std::ranges::find_if(users, [](const User& u) {
return u.email == "admin@example.com";
});
std::ranges::sort(users, {}, &User::name); // Project by name
```
## Error Handling
### Exceptions vs Error Codes
```cpp
// ✅ Use exceptions for exceptional conditions
class NetworkError : public std::runtime_error {
public:
explicit NetworkError(const std::string& message)
: std::runtime_error(message) {}
};
void fetch_data(const std::string& url) {
if (!is_connected()) {
throw NetworkError("No network connection");
}
// ...
}
// ✅ Use std::expected (C++23) for expected failures
std::expected<User, Error> find_user(const std::string& id) {
auto it = users_.find(id);
if (it == users_.end()) {
return std::unexpected(Error::NotFound);
}
return it->second;
}
// ✅ Handle expected results
auto result = find_user("123");
if (result) {
process(*result);
} else {
handle_error(result.error());
}
```
### noexcept Specification
```cpp
// ✅ Mark non-throwing functions noexcept
int get_value() const noexcept { return value_; }
// ✅ Move operations should be noexcept
Buffer(Buffer&& other) noexcept;
Buffer& operator=(Buffer&& other) noexcept;
// ✅ Swap should be noexcept
void swap(Buffer& other) noexcept {
using std::swap;
swap(data_, other.data_);
swap(size_, other.size_);
}
// ✅ Destructors are implicitly noexcept
~Buffer(); // noexcept by default
```
## Const Correctness
```cpp
// ✅ Use const everywhere possible
class User {
public:
// Const member function
std::string get_name() const { return name_; }
// Const reference parameter
void set_name(const std::string& name) { name_ = name; }
// Const reference return
const std::string& name() const { return name_; }
private:
std::string name_;
};
// ✅ Const for local variables
const auto user = find_user("123");
const int max_size = calculate_max_size();
// ✅ Const iterators
for (const auto& item : items) {
// Can't modify item
}
// ✅ constexpr for compile-time computation
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}
constexpr int fact5 = factorial(5); // Computed at compile time
```
## Memory Safety
### Avoid Common Pitfalls
```cpp
// ❌ Dangling reference
const std::string& get_name() {
std::string name = "Alice";
return name; // ❌ Dangling!
}
// ✅ Return by value
std::string get_name() {
return "Alice";
}
// ❌ Use after move
std::vector<int> data = {1, 2, 3};
process(std::move(data));
data.size(); // ❌ UB: moved-from
// ✅ Clear after move if reusing
std::vector<int> data = {1, 2, 3};
process(std::move(data));
data = {4, 5, 6}; // OK: reassigned
// ❌ Iterator invalidation
std::vector<int> v = {1, 2, 3};
for (auto it = v.begin(); it != v.end(); ++it) {
if (*it == 2) v.push_back(4); // ❌ Invalidates iterator!
}
// ✅ Use erase-remove idiom
v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());
// Or C++20: std::erase_if(v, pred);
```
### Bounds Checking
```cpp
// ✅ Use at() for checked access
try {
auto value = vec.at(index);
} catch (const std::out_of_range& e) {
// Handle error
}
// ✅ Use span (C++20) for safe array passing
void process(std::span<const int> data) {
for (int value : data) {
// Safe iteration
}
}
// ✅ Use string_view for non-owning strings
void print(std::string_view text) {
std::cout << text << '\n';
}
```
## Concurrency
### Thread Safety
```cpp
// ✅ Use mutex for shared data
class ThreadSafeCounter {
public:
void increment() {
std::lock_guard<std::mutex> lock(mutex_);
++count_;
}
int get() const {
std::lock_guard<std::mutex> lock(mutex_);
return count_;
}
private:
mutable std::mutex mutex_;
int count_ = 0;
};
// ✅ Use atomic for simple types
class AtomicCounter {
public:
void increment() {
count_.fetch_add(1, std::memory_order_relaxed);
}
int get() const {
return count_.load(std::memory_order_relaxed);
}
private:
std::atomic<int> count_{0};
};
// ✅ Use jthread (C++20) for auto-joining
void run_background_task() {
std::jthread worker([](std::stop_token token) {
while (!token.stop_requested()) {
do_work();
}
});
// Automatically joins on destruction
}
```
### Async Programming
```cpp
// ✅ Use async for parallel work
auto future = std::async(std::launch::async, [] {
return expensive_computation();
});
// ... do other work ...
auto result = future.get();
// ✅ Use promise/future for communication
std::promise<int> promise;
std::future<int> future = promise.get_future();
std::thread worker([&promise] {
auto result = compute();
promise.set_value(result);
});
auto value = future.get();
worker.join();
```
## Testing
### GoogleTest
```cpp
#include <gtest/gtest.h>
class UserTest : public ::testing::Test {
protected:
void SetUp() override {
user_ = std::make_unique<User>("Alice", "alice@example.com");
}
std::unique_ptr<User> user_;
};
TEST_F(UserTest, ConstructorSetsName) {
EXPECT_EQ(user_->name(), "Alice");
}
TEST_F(UserTest, ConstructorSetsEmail) {
EXPECT_EQ(user_->email(), "alice@example.com");
}
TEST(EmailValidation, ValidEmailsPass) {
EXPECT_TRUE(is_valid_email("user@example.com"));
EXPECT_TRUE(is_valid_email("user.name@subdomain.example.com"));
}
TEST(EmailValidation, InvalidEmailsFail) {
EXPECT_FALSE(is_valid_email("invalid"));
EXPECT_FALSE(is_valid_email("@example.com"));
}
// ✅ Parameterized tests
class EmailValidationTest : public ::testing::TestWithParam<std::pair<std::string, bool>> {};
TEST_P(EmailValidationTest, ValidatesCorrectly) {
auto [email, expected] = GetParam();
EXPECT_EQ(is_valid_email(email), expected);
}
INSTANTIATE_TEST_SUITE_P(Emails, EmailValidationTest,
::testing::Values(
std::make_pair("user@example.com", true),
std::make_pair("invalid", false)
));
```
## Clang-Tidy Configuration
```yaml
# .clang-tidy
Checks: >
-*,
bugprone-*,
clang-analyzer-*,
cppcoreguidelines-*,
misc-*,
modernize-*,
performance-*,
readability-*,
-modernize-use-trailing-return-type,
-readability-magic-numbers,
-cppcoreguidelines-avoid-magic-numbers
WarningsAsErrors: ""
CheckOptions:
- key: readability-identifier-naming.ClassCase
value: CamelCase
- key: readability-identifier-naming.FunctionCase
value: lower_case
- key: readability-identifier-naming.VariableCase
value: lower_case
- key: readability-identifier-naming.ConstantCase
value: UPPER_CASE
- key: readability-identifier-naming.MemberSuffix
value: "_"
- key: performance-unnecessary-value-param.AllowedTypes
value: "std::string_view;std::span"
```
## Validation Checklist
```text
□ No raw new/delete (use smart pointers)
□ RAII for all resource management
□ Move semantics implemented correctly
□ noexcept on move operations
□ Const correctness throughout
□ No dangling references/pointers
□ Thread-safe shared data access
□ Range-based for loops preferred
□ std::optional for absent values
□ Concepts used for template constraints
□ clang-tidy passes
□ Tests cover edge cases
```
## Resources
- [C++ Core Guidelines](https://isocpp.github.io/CppCoreGuidelines/)
- [CPP Reference](https://en.cppreference.com/)
- [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html)
- [Effective Modern C++ (Scott Meyers)](https://www.oreilly.com/library/view/effective-modern-c/9781491908419/)
- [C++ Best Practices (Jason Turner)](https://github.com/cpp-best-practices)
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.