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 refactorizar código C++ para aplicar prácticas modernas, seguras e idiomáticas.

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

Esta habilidad proporciona un conjunto completo de reglas de codificación C++ modernas (C++17/20/23) derivadas de las C++ Core Guidelines. Es útil para cualquier desarrollador que trabaje con C++ y busque mejorar la seguridad, claridad y mantenibilidad de su código. La habilidad cubre principios clave como RAII, inmutabilidad, seguridad de tipos y minimización de la complejidad, y se organiza en secciones detalladas que abarcan filosofía, interfaces, funciones, clases, gestión de recursos, expresiones, manejo de errores, constantes y concurrencia. Se incluyen ejemplos de código y antipatrones, y la habilidad se aplica al escribir, revisar o refactorizar código C++ en cualquier plataforma o herramienta de desarrollo (como compiladores, IDEs o pipelines CI/CD).

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/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 integrales 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 nuevo código C++ (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 sin procesar 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/de metal desnudo 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 útil del recurso a la vida útil 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 la intención (P.3, F.1, NL.1-2, T.10): Los nombres, tipos y conceptos deben comunicar el propósito
  5. Minimizar la 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 la intención
P.4Idealmente, un programa debe ser estáticamente seguro en tipos
P.5Preferir la comprobación en tiempo de compilación a la 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 precisas y fuertemente tipadas
I.11Nunca transferir propiedad mediante un puntero o referencia sin procesar
I.23Mantener bajo el número de argumentos de función

HACER

// P.10 + I.4: Interfaz inmutable y 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 única 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 su función no debe lanzar excepciones, declararla noexcept
F.8Preferir funciones puras
F.16Para parámetros "de entrada", pasar tipos de copia barata 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 cuando sea posible
constexpr int factorial(int n) noexcept {
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

static_assert(factorial(5) == 120);

Antipatrones

  • 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 puede evitar definir operaciones por defecto, hágalo (Regla de Cero)
C.21Si define o =delete cualquier copia/movimiento/destructor, manéjelos todos (Regla de Cinco)
C.35Destructor de clase base: virtual público o virtual protegido 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 la 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 necesita destructor, constructores de copia/movimiento ni operadores de asignación
};

Regla de Cinco

// C.21: Si debe gestionar un recurso, definir 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_;
};

Antipatrones

  • Llamar funciones virtuales en constructores/destructores (C.82)
  • Usar memset/memcpy en tipos no triviales (C.90)
  • Proporcionar diferentes argumentos por defecto para función virtual y sobreescritura (C.140)
  • Hacer miembros de datos 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 sin procesar (T*) no es propietario
R.5Preferir objetos con ámbito; no asignar en el montón 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 sin procesar = observador no propietario
void render(const Widget* w) {  // NO es propietario de 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_;
};

Antipatrones

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

Expresiones y Sentencias (ES.*)

Reglas Clave

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

Inicialización

// ES.20 + ES.23 + ES.25: Inicializar siempre, 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;
}();

Antipatrones

  • Variables no inicializadas (ES.20)
  • Usar 0 o NULL como puntero (ES.47 -- usar nullptr)
  • Conversiones de tipo al estilo C (ES.48 -- usar static_cast, const_cast, etc.)
  • Eliminar const mediante cast (ES.50)
  • Números mágicos sin constantes con nombre (ES.45)
  • Mezclar aritmética con 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 evitar 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.16Destructores, 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
}

Antipatrones

  • Lanzar tipos integrados como int o literales de cadena (E.14)
  • Capturar por valor (riesgo de división/doble tipo) (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-const 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 intercambio explícito de datos modificables
CP.4Pensar en términos de tareas, en lugar de hilos
CP.8No usar volatile para sincronización
CP.20Usar RAII, nunca usar lock()/unlock() simples
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 sus 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_);
        queue_.push(value);
    }

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

    bool empty() const {
        std::scoped_lock lock(mutex_);
        return queue_.empty();
    }

private:
    mutable std::mutex mutex_;
    std::queue<int> queue_;
};

Tareas vs Hilos

// CP.4: Pensar en tareas
std::future<int> result = std::async(std::launch::async, [] {
    return heavy_computation();
});

// ... otro trabajo ...

int value = result.get();  // esperar y obtener el resultado

Antipatrones

  • Usar volatile para sincronización (CP.8)
  • Esperar ocupado sin una variable de condición (CP.42)
  • Llamar código de usuario mientras se mantiene un bloqueo (CP.22)
  • lock() / unlock() manual (CP.20)
  • Adquirir múltiples mutex sin std::scoped_lock (CP.21)

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/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

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.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

Skills relacionados