Communitygithub.com

Estándares de Codificación C++

Estándares de codificación C++ basados en las C++ Core Guidelines (isocpp.github.io). Úselos al escribir, revisar o refaccionar código C++ para aplicar prácticas modernas, seguras e idiomáticas.

¿Qué es Estándares de Codificación C++?

Este skill proporciona un conjunto completo de estándares de codificación para C++ moderno (C++17/20/23) derivados de las C++ Core Guidelines oficiales. Su objetivo es mejorar la seguridad de tipos, la gestión de recursos, la inmutabilidad y la claridad del código. Cubre principios fundamentales como RAII, inmutabilidad por defecto, semántica de valor sobre punteros, y expresa intención directamente en el código. Incluye reglas detalladas para interfaces, funciones, clases, gestión de recursos, expresiones, manejo de errores, constantes y concurrencia, con ejemplos de código que muestran tanto buenas prácticas como anti-patrones a evitar. Es útil para desarrolladores que trabajan en proyectos C++ modernos, ya sea escribiendo código nuevo, revisando existente o tomando decisiones arquitectónicas. El skill está diseñado para integrarse en asistentes de codificación como Claude Code, Cursor o Codex, proporcionando guías claras y accionables directamente en el flujo de trabajo.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/everything-claude-code/tree/main/skills/cpp-coding-standards

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Estándares de Codificación C++ (C++ Core Guidelines)

Estándares de codificación completos para C++ moderno (C++17/20/23) derivados de las C++ Core Guidelines. Aplica seguridad de tipos, seguridad de recursos, inmutabilidad y claridad.

Cuándo Usar

  • Escribir código C++ nuevo (clases, funciones, plantillas)
  • Revisar o refactorizar código C++ existente
  • Tomar decisiones arquitectónicas en proyectos C++
  • Aplicar un estilo consistente en un código base C++
  • Elegir entre características del lenguaje (ej., enum vs enum class, puntero crudo vs puntero inteligente)

Cuándo NO Usar

  • Proyectos que no sean C++
  • Código base C heredado que no pueda adoptar características modernas de C++
  • Contextos embebidos/sin sistema operativo donde guías específicas entren en conflicto con restricciones de hardware (adaptar selectivamente)

Principios Transversales

Estos temas se repiten en todas las guías y forman la base:

  1. RAII en todas partes (P.8, R.1, E.6, CP.20): Vincular la vida del recurso a la vida del objeto
  2. Inmutabilidad por defecto (P.10, Con.1-5, ES.25): Comenzar con const/constexpr; la mutabilidad es la excepción
  3. Seguridad de tipos (P.4, I.4, ES.46-49, Enum.3): Usar el sistema de tipos para prevenir errores en tiempo de compilación
  4. Expresar intención (P.3, F.1, NL.1-2, T.10): Nombres, tipos y conceptos deben comunicar propósito
  5. Minimizar complejidad (F.2-3, ES.5, Per.4-5): El código simple es código correcto
  6. Semántica de valor sobre semántica de puntero (C.10, R.3-5, F.20, CP.31): Preferir devolver por valor y objetos con ámbito

Filosofía e Interfaces (P., I.)

Reglas Clave

ReglaResumen
P.1Expresar ideas directamente en código
P.3Expresar intención
P.4Idealmente, un programa debe ser estáticamente seguro en tipos
P.5Preferir comprobación en tiempo de compilación a comprobación en tiempo de ejecución
P.8No filtrar ningún recurso
P.10Preferir datos inmutables a datos mutables
I.1Hacer las interfaces explícitas
I.2Evitar variables globales no constantes
I.4Hacer las interfaces precisa y fuertemente tipadas
I.11Nunca transferir propiedad mediante un puntero crudo o referencia
I.23Mantener bajo el número de argumentos de función

HACER

// P.10 + I.4: Interfaz inmutable fuertemente tipada
struct Temperature {
    double kelvin;
};

Temperature boil(const Temperature& water);

NO HACER

// Interfaz débil: propiedad poco clara, unidades poco claras
double boil(double* temp);

// Variable global no constante
int g_counter = 0;  // violación I.2

Funciones (F.*)

Reglas Clave

ReglaResumen
F.1Empaquetar operaciones significativas como funciones cuidadosamente nombradas
F.2Una función debe realizar una sola operación lógica
F.3Mantener las funciones cortas y simples
F.4Si una función puede evaluarse en tiempo de compilación, declararla constexpr
F.6Si una función no debe lanzar excepciones, declararla noexcept
F.8Preferir funciones puras
F.16Para parámetros "de entrada", pasar tipos baratos de copiar por valor y otros por const&
F.20Para valores "de salida", preferir valores de retorno a parámetros de salida
F.21Para devolver múltiples valores "de salida", preferir devolver una estructura
F.43Nunca devolver un puntero o referencia a un objeto local

Paso de Parámetros

// F.16: Tipos baratos por valor, otros por const&
void print(int x);                           // barato: por valor
void analyze(const std::string& data);       // costoso: por const&
void transform(std::string s);               // sumidero: por valor (se moverá)

// F.20 + F.21: Valores de retorno, no parámetros de salida
struct ParseResult {
    std::string token;
    int position;
};

ParseResult parse(std::string_view input);   // BIEN: devolver estructura

// MAL: parámetros de salida
void parse(std::string_view input,
           std::string& token, int& pos);    // evitar esto

Funciones Puras y constexpr

// F.4 + F.8: Pura, constexpr donde sea posible
constexpr int factorial(int n) noexcept {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

static_assert(factorial(5) == 120);

Anti-patrones

  • Devolver T&& desde funciones (F.45)
  • Usar va_arg / variádicos al estilo C (F.55)
  • Capturar por referencia en lambdas pasadas a otros hilos (F.53)
  • Devolver const T que inhibe la semántica de movimiento (F.49)

Clases y Jerarquías de Clases (C.*)

Reglas Clave

ReglaResumen
C.2Usar class si existe invariante; struct si los miembros de datos varían independientemente
C.9Minimizar la exposición de miembros
C.20Si puedes evitar definir operaciones predeterminadas, hazlo (Regla de Cero)
C.21Si defines o =delete cualquier constructor copia/movimiento/destructor, manéjalos todos (Regla de Cinco)
C.35Destructor de clase base: public virtual o protected no virtual
C.41Un constructor debe crear un objeto completamente inicializado
C.46Declarar constructores de un solo argumento como explicit
C.67Una clase polimórfica debe suprimir copia/movimiento públicos
C.128Funciones virtuales: especificar exactamente uno de virtual, override, o final

Regla de Cero

// C.20: Dejar que el compilador genere los miembros especiales
struct Employee {
    std::string name;
    std::string department;
    int id;
    // No se necesitan destructor, constructores copia/movimiento, ni operadores de asignación
};

Regla de Cinco

// C.21: Si debes gestionar un recurso, define los cinco
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_;
};

Jerarquía de Clases

// C.35 + C.128: Destructor virtual, usar override
class Shape {
public:
    virtual ~Shape() = default;
    virtual double area() const = 0;  // C.121: interfaz pura
};

class Circle : public Shape {
public:
    explicit Circle(double r) : radius_(r) {}
    double area() const override { return 3.14159 * radius_ * radius_; }

private:
    double radius_;
};

Anti-patrones

  • Llamar a funciones virtuales en constructores/destructores (C.82)
  • Usar memset/memcpy en tipos no triviales (C.90)
  • Proporcionar argumentos predeterminados diferentes para una función virtual y su reemplazo (C.140)
  • Hacer que los miembros de datos sean const o referencias, lo que suprime movimiento/copia (C.12)

Gestión de Recursos (R.*)

Reglas Clave

ReglaResumen
R.1Gestionar recursos automáticamente usando RAII
R.3Un puntero crudo (T*) no posee
R.5Preferir objetos con ámbito; no asignar en el montículo innecesariamente
R.10Evitar malloc()/free()
R.11Evitar llamar a new y delete explícitamente
R.20Usar unique_ptr o shared_ptr para representar propiedad
R.21Preferir unique_ptr sobre shared_ptr a menos que se comparta la propiedad
R.22Usar make_shared() para crear shared_ptrs

Uso de Punteros Inteligentes

// R.11 + R.20 + R.21: RAII con punteros inteligentes
auto widget = std::make_unique<Widget>("config");  // propiedad única
auto cache  = std::make_shared<Cache>(1024);        // propiedad compartida

// R.3: Puntero crudo = observador no propietario
void render(const Widget* w) {  // NO posee w
    if (w) w->draw();
}

render(widget.get());

Patrón RAII

// R.1: La adquisición de recursos es inicialización
class FileHandle {
public:
    explicit FileHandle(const std::string& path)
        : handle_(std::fopen(path.c_str(), "r")) {
        if (!handle_) throw std::runtime_error("Error al abrir: " + 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_;
};

Anti-patrones

  • new/delete directos (R.11)
  • malloc()/free() en código C++ (R.10)
  • Múltiples asignaciones de recursos en una sola expresión (R.13 -- peligro de seguridad de excepciones)
  • shared_ptr donde unique_ptr es suficiente (R.21)

Expresiones y Sentencias (ES.*)

Reglas Clave

ReglaResumen
ES.5Mantener los ámbitos pequeños
ES.20Inicializar siempre un objeto
ES.23Preferir sintaxis de inicializador {}
ES.25Declarar objetos const o constexpr a menos que se pretenda modificación
ES.28Usar lambdas para inicialización compleja de variables const
ES.45Evitar constantes mágicas; usar constantes simbólicas
ES.46Evitar conversiones aritméticas de estrechamiento/con pérdida
ES.47Usar nullptr en lugar de 0 o NULL
ES.48Evitar conversiones de tipo
ES.50No eliminar const con un cast

Inicialización

// ES.20 + ES.23 + ES.25: Siempre inicializar, preferir {}, por defecto const
const int max_retries{3};
const std::string name{"widget"};
const std::vector<int> primes{2, 3, 5, 7, 11};

// ES.28: Lambda para inicialización const compleja
const auto config = [&] {
    Config c;
    c.timeout = std::chrono::seconds{30};
    c.retries = max_retries;
    c.verbose = debug_mode;
    return c;
}();

Anti-patrones

  • Variables no inicializadas (ES.20)
  • Usar 0 o NULL como puntero (ES.47 -- usar nullptr)
  • Conversiones al estilo C (ES.48 -- usar static_cast, const_cast, etc.)
  • Eliminar const con un cast (ES.50)
  • Números mágicos sin constantes con nombre (ES.45)
  • Mezclar aritmética con signo y sin signo (ES.100)
  • Reutilizar nombres en ámbitos anidados (ES.12)

Manejo de Errores (E.*)

Reglas Clave

ReglaResumen
E.1Desarrollar una estrategia de manejo de errores temprano en el diseño
E.2Lanzar una excepción para señalar que una función no puede realizar su tarea asignada
E.6Usar RAII para prevenir fugas
E.12Usar noexcept cuando lanzar sea imposible o inaceptable
E.14Usar tipos definidos por el usuario diseñados específicamente como excepciones
E.15Lanzar por valor, capturar por referencia
E.16Los destructores, desasignación y swap nunca deben fallar
E.17No intentar capturar cada excepción en cada función

Jerarquía de Excepciones

// E.14 + E.15: Tipos de excepción personalizados, lanzar por valor, capturar por referencia
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: Lanzar para señalar fallo
    throw NetworkError("conexión rechazada", 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: No capturar todo aquí -- dejar que los errores inesperados se propaguen
}

Anti-patrones

  • Lanzar tipos integrados como int o literales de cadena (E.14)
  • Capturar por valor (riesgo de segmentación) (E.15)
  • Bloques catch vacíos que tragan errores silenciosamente
  • Usar excepciones para control de flujo (E.3)
  • Manejo de errores basado en estado global como errno (E.28)

Constantes e Inmutabilidad (Con.*)

Todas las Reglas

ReglaResumen
Con.1Por defecto, hacer los objetos inmutables
Con.2Por defecto, hacer las funciones miembro const
Con.3Por defecto, pasar punteros y referencias a const
Con.4Usar const para valores que no cambian después de la construcción
Con.5Usar constexpr para valores computables en tiempo de compilación
// Con.1 a Con.5: Inmutabilidad por defecto
class Sensor {
public:
    explicit Sensor(std::string id) : id_(std::move(id)) {}

    // Con.2: funciones miembro const por defecto
    const std::string& id() const { return id_; }
    double last_reading() const { return reading_; }

    // Solo no constante cuando se requiere mutación
    void record(double value) { reading_ = value; }

private:
    const std::string id_;  // Con.4: nunca cambia después de la construcción
    double reading_{0.0};
};

// Con.3: Pasar por referencia constante
void display(const Sensor& s) {
    std::cout << s.id() << ": " << s.last_reading() << '\n';
}

// Con.5: Constantes en tiempo de compilación
constexpr double PI = 3.14159265358979;
constexpr int MAX_SENSORS = 256;

Concurrencia y Paralelismo (CP.*)

Reglas Clave

ReglaResumen
CP.2Evitar condiciones de carrera
CP.3Minimizar el compartir explícito de datos modificables
CP.4Pensar en términos de tareas, más que de hilos
CP.8No usar volatile para sincronización
CP.20Usar RAII, nunca lock()/unlock() directos
CP.21Usar std::scoped_lock para adquirir múltiples mutex
CP.22Nunca llamar código desconocido mientras se mantiene un bloqueo
CP.42No esperar sin una condición
CP.44Recordar nombrar tus lock_guards y unique_locks
CP.100No usar programación libre de bloqueos a menos que sea absolutamente necesario

Bloqueo Seguro

// CP.20 + CP.44: Bloqueos RAII, siempre nombrados
class ThreadSafeQueue {
public:
    void push(int value) {
        std::scoped_lock lock(mutex_);  // CP.21: adquiere mutex(es) de forma segura
        data_.push(value);
    }

    std::optional<int> pop() {
        std::scoped_lock lock(mutex_);
        if (data_.empty()) return std::nullopt;
        int value = data_.front();
        data_.pop();
        return value;
    }

private:
    std::queue<int> data_;
    mutable std::mutex mutex_;  // mutable porque lock_guard modifica el mutex en métodos const
};

Conclusión

Seguir las C++ Core Guidelines conduce a un código que es:

  • Seguro: Los errores se detectan en tiempo de compilación mediante el sistema de tipos
  • Eficiente: Las abstracciones tienen costo cero o mínimo
  • Mantenible: La intención es clara, los recursos se gestionan automáticamente
  • Moderno: Aprovecha las características de C++17/20/23 para simplificar el código

Consulte siempre las C++ Core Guidelines completas para obtener explicaciones detalladas y ejemplos.

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/claude-api

Anthropic Claude API patterns for Python and TypeScript. Covers Messages API, streaming, tool use, vision, extended thinking, batches, prompt caching, and Claude Agent SDK. Use when building applications with the Claude API or Anthropic SDKs.

affaan-m/everything-claude-code

End-to-end marketing campaign planning and execution. Covers audience research, positioning, campaign angle definition, landing page copy, email sequences, social posts, ad copy, short-form video scripts, and content calendars. Use as the orchestration layer for multi-channel product launches. Use when planning or executing a multi-channel product launch, or producing landing page, email, social, or ad copy.

affaan-m/everything-claude-code

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/everything-claude-code-conventions

Development conventions and patterns for everything-claude-code. JavaScript project with conventional commits.

affaan-m/frontend-design

Create distinctive, production-grade frontend interfaces with high design quality. Use when the user asks to build web components, pages, or applications and the visual direction matters as much as the code quality.

affaan-m/gget

gget CLI and Python workflow for quick genomic database queries, sequence lookup, BLAST-style searches, enrichment checks, and reproducible bioinformatics evidence logs.

affaan-m/literature-review

Systematic literature-review workflow for academic, biomedical, technical, and scientific topics, including search planning, source screening, synthesis, citation checks, and evidence logging.

affaan-m/motion-ui

Production-ready UI motion system for React/Next.js. Use when implementing animations, transitions, or motion patterns.

affaan-m/project-guidelines-example

Example project-specific skill template based on a real production application.

affaan-m/pubmed-database

Direct PubMed and NCBI E-utilities search workflows for biomedical literature, MeSH queries, PMID lookup, citation retrieval, and API-backed literature monitoring.

affaan-m/scholar-evaluation

Structured scholarly-work evaluation for papers, proposals, literature reviews, methods sections, evidence quality, citation support, and research-writing feedback.

affaan-m/uspto-database

USPTO patent and trademark data workflow for official record lookup, PatentSearch queries, TSDR checks, assignment data, and reproducible IP research logs.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

Skills relacionados