Production-ready C/C++ coding standards enforcing safety, modern patterns, and maintainability. Use when enforcing cpp coding conventions and style rules.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill cpp-coding-standards --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Cpp Coding Standards?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-cpp-coding-standards)More formats (shields.io, HTML) on the badges page.
---
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)
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!