Skip to content
Overview History Stats Security
SkillBundle Find AI coding assistant skills, watch the ones you depend on, and see what changed.
© 2026 SkillBundle
Skill metadata from skills.sh and public GitHub repositories.
npx skills add affaan-m/ecc --skill cpp-coding-standards cpp-coding-standards | SkillBundle
C++ coding standards based on the C++ Core Guidelines (isocpp.github.io). Use when writing, reviewing, or refactoring C++ code to enforce modern, safe, and idiomatic practices.
npx skills add affaan-m/ecc --skill cpp-coding-standards
);
// Weak interface: unclear ownership, unclear units
double boil ( double* temp );
// Non-const global variable
int g_counter = 0 ; // I.2 violation // F.16: Cheap types by value, others by const&
void print ( int x ); // cheap: by value
void analyze ( const std :: string & data ); // expensive: by const&
void transform ( std :: string s ); // sink: by value (will move)
// F.20 + F.21: Return values, not output parameters
struct ParseResult {
std ::string token;
int position;
};
ParseResult parse ( std :: string_view input ); // GOOD: return struct
// BAD: output parameters
void parse ( std :: string_view input ,
std :: string & token , int& pos ); // avoid this // F.4 + F.8: Pure, constexpr where possible
constexpr int factorial ( int n ) noexcept {
return (n <= 1 ) ? 1 : n * factorial (n - 1 );
}
static_assert ( factorial ( 5 ) == 120 ); // C.20: Let the compiler generate special members
struct Employee {
std ::string name;
std ::string department;
int id;
// No destructor, copy/move constructors, or assignment operators needed
}; // C.21: If you must manage a resource, define all five
class Buffer {
public:
explicit Buffer ( std :: size_t size )
: data_ ( std :: make_unique < char []>(size)), size_ (size) {}
~Buffer () = default ;
Buffer ( const Buffer & other )
: data_ ( std :: make_unique < char []>(other.size_)), size_ (other.size_) {
std :: copy_n (other.data_. get (), size_, data_. get ());
}
Buffer & operator = ( const Buffer & other ) {
if ( this != & other) {
auto new_data = std :: make_unique < char []>(other.size_);
std :: copy_n (other.data_. get (), other.size_, new_data. get ());
data_ = std :: move (new_data);
size_ = other.size_;
}
return * this ;
}
Buffer ( Buffer && ) noexcept = default ;
Buffer & operator = ( Buffer && ) noexcept = default ;
private:
std ::unique_ptr <char [] > data_;
std :: size_t size_;
}; // C.35 + C.128: Virtual destructor, use override
class Shape {
public:
virtual ~Shape () = default ;
virtual double area () const = 0 ; // C.121: pure interface
};
class Circle : public Shape {
public:
explicit Circle ( double r ) : radius_ (r) {}
double area () const override { return 3.14159 * radius_ * radius_; }
private:
double radius_;
}; // R.11 + R.20 + R.21: RAII with smart pointers
auto widget = std :: make_unique < Widget >( "config" ); // unique ownership
auto cache = std :: make_shared < Cache >( 1024 ); // shared ownership
// R.3: Raw pointer = non-owning observer
void render ( const Widget * w ) { // does NOT own w
if (w) w-> draw ();
}
render (widget. get ()); // R.1: Resource acquisition is initialization
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: " + path);
}
~FileHandle () {
if (handle_) std :: fclose (handle_);
}
FileHandle ( const FileHandle & ) = delete ;
FileHandle & operator = ( const FileHandle & ) = delete ;
FileHandle ( FileHandle && other ) noexcept
: handle_ ( std :: exchange (other.handle_, nullptr )) {}
FileHandle & operator = ( FileHandle && other ) noexcept {
if ( this != & other) {
if (handle_) std :: fclose (handle_);
handle_ = std :: exchange (other.handle_, nullptr );
}
return * this ;
}
private:
std ::FILE * handle_;
}; // ES.20 + ES.23 + ES.25: Always initialize, prefer {}, default to const
const int max_retries{ 3 };
const std ::string name{ "widget" };
const std ::vector <int> primes{ 2 , 3 , 5 , 7 , 11 };
// ES.28: Lambda for complex const initialization
const auto config = [ & ] {
Config c;
c.timeout = std :: chrono ::seconds{ 30 };
c.retries = max_retries;
c.verbose = debug_mode;
return c;
}(); // E.14 + E.15: Custom exception types, throw by value, catch by reference
class AppError : public std :: runtime_error {
public:
using std :: runtime_error ::runtime_error;
};
class NetworkError : public AppError {
public:
NetworkError ( const std :: string & msg , int code )
: AppError (msg), status_code (code) {}
int status_code;
};
void fetch_data ( const std :: string & url ) {
// E.2: Throw to signal failure
throw NetworkError ( "connection refused" , 503 );
}
void run () {
try {
fetch_data ( "https://api.example.com" );
} catch ( const NetworkError & e) {
log_error (e. what (), e.status_code);
} catch ( const AppError & e) {
log_error (e. what ());
}
// E.17: Don't catch everything here -- let unexpected errors propagate
} // Con.1 through Con.5: Immutability by default
class Sensor {
public:
explicit Sensor ( std :: string id ) : id_ ( std :: move (id)) {}
// Con.2: const member functions by default
const std :: string & id () const { return id_; }
double last_reading () const { return reading_; }
// Only non-const when mutation is required
void record ( double value ) { reading_ = value; }
private:
const std ::string id_; // Con.4: never changes after construction
double reading_{ 0.0 };
};
// Con.3: Pass by const reference
void display ( const Sensor & s ) {
std ::cout << s. id () << ": " << s. last_reading () << ' \n ' ;
}
// Con.5: Compile-time constants
constexpr double PI = 3.14159265358979 ;
constexpr int MAX_SENSORS = 256 ; // CP.20 + CP.44: RAII locks, always named
class ThreadSafeQueue {
public:
void push ( int value ) {
std ::lock_guard < std ::mutex > lock (mutex_); // CP.44: named!
queue_. push (value);
cv_. notify_one ();
}
int pop () {
std ::unique_lock < std ::mutex > lock (mutex_);
// CP.42: Always wait with a condition
cv_. wait (lock, [ this ] { return ! queue_. empty (); });
const int value = queue_. front ();
queue_. pop ();
return value;
}
private:
std ::mutex mutex_; // CP.50: mutex with its data
std ::condition_variable cv_;
std ::queue <int> queue_;
}; // CP.21: std::scoped_lock for multiple mutexes (deadlock-free)
void transfer ( Account & from , Account & to , double amount ) {
std ::scoped_lock lock (from.mutex_, to.mutex_);
from.balance_ -= amount;
to.balance_ += amount;
} #include <concepts>
// T.10 + T.11: Constrain templates with standard concepts
template < std :: integral T >
T gcd ( T a , T b ) {
while (b != 0 ) {
a = std :: exchange (b, a % b);
}
return a;
}
// T.13: Shorthand concept syntax
void sort ( std :: ranges :: random_access_range auto& range ) {
std :: ranges :: sort (range);
}
// Custom concept for domain-specific constraints
template < typename T >
concept Serializable = requires ( const T & t) {
{ t. serialize () } -> std ::convertible_to < std ::string > ;
};
template < Serializable T >
void save ( const T & obj , const std :: string & path ); // SL.con.1 + SL.con.2: Prefer vector/array over C arrays
const std ::array <int , 4 > fixed_data{ 1 , 2 , 3 , 4 };
std ::vector < std ::string > dynamic_data;
// SL.str.1 + SL.str.2: string owns, string_view observes
std :: string build_greeting ( std :: string_view name ) {
return "Hello, " + std :: string (name) + "!" ;
}
// SL.io.50: Use '\n' not endl
std ::cout << "result: " << value << ' \n ' ; // Enum.3 + Enum.5: Scoped enum, no ALL_CAPS
enum class Color { red , green , blue };
enum class LogLevel { debug , info , warning , error };
// BAD: plain enum leaks names, ALL_CAPS clashes with macros
enum { RED , GREEN , BLUE }; // Enum.3 + Enum.5 + Enum.6 violation
#define MAX_SIZE 100 // Enum.1 violation -- use constexpr // SF.8: Include guard (or #pragma once)
#ifndef PROJECT_MODULE_WIDGET_H
#define PROJECT_MODULE_WIDGET_H
// SF.11: Self-contained -- include everything this header needs
#include <string>
#include <vector>
namespace project :: module {
class Widget {
public:
explicit Widget ( std :: string name );
const std :: string & name () const ;
private:
std ::string name_;
};
} // namespace project::module
#endif // PROJECT_MODULE_WIDGET_H // NL.8 + NL.10: Consistent underscore_style
namespace my_project {
constexpr int max_buffer_size = 4096 ; // NL.9: not ALL_CAPS (it's not a macro)
class tcp_connection { // underscore_style class
public:
void send_message ( std :: string_view msg );
bool is_connected () const ;
private:
std ::string host_; // trailing underscore for members
int port_;
};
} // namespace my_project // Per.11: Compile-time computation where possible
constexpr auto lookup_table = [] {
std ::array <int , 256 > table{};
for ( int i = 0 ; i < 256 ; ++ i) {
table[i] = i * i;
}
return table;
}();
// Per.19: Prefer contiguous data for cache-friendliness
std ::vector < Point > points; // GOOD: contiguous
std ::vector < std ::unique_ptr < Point >> indirect_points; // BAD: pointer chasing