Communitygithub.com

normes-cpp

Normes de codage C++ basées sur les C++ Core Guidelines (isocpp.github.io). À utiliser lors de l'écriture, la relecture ou le refactoring de code C++ pour appliquer des pratiques modernes, sûres et idiomatiques.

Qu'est-ce que normes-cpp ?

Cette compétence fournit une référence complète de normes de codage pour le C++ moderne (C++17/20/23), dérivées des C++ Core Guidelines. Elle couvre les principes transversaux (RAII, immutabilité, sécurité de type, etc.) et des règles détaillées pour les interfaces, les fonctions, les classes, la gestion des ressources, les expressions, la gestion des erreurs, les constantes, la concurrence et les métadonnées de compilation. Chaque section comprend des règles clés, des exemples de code "à faire" et "à ne pas faire", et des anti-patrons. Les développeurs peuvent l'utiliser pour écrire du nouveau code C++, relire ou refactorer du code existant, prendre des décisions architecturales, ou assurer une cohérence de style dans une base de code. La compétence est conçue pour être utilisée avec des assistants de codage IA comme Claude Code, Cursor ou Codex, en extrayant les sections pertinentes selon la tâche.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Normes de codage C++ (C++ Core Guidelines)

Normes de codage complètes pour le C++ moderne (C++17/20/23) dérivées des C++ Core Guidelines. Applique la sécurité de type, la sécurité des ressources, l'immutabilité et la clarté.

Quand l'utiliser

  • Écrire du nouveau code C++ (classes, fonctions, templates)
  • Relire ou refactorer du code C++ existant
  • Prendre des décisions architecturales dans des projets C++
  • Appliquer un style cohérent dans une base de code C++
  • Choisir entre des fonctionnalités du langage (par exemple, enum vs enum class, pointeur nu vs pointeur intelligent)

Quand NE PAS l'utiliser

  • Projets non C++
  • Bases de code C héritées qui ne peuvent pas adopter les fonctionnalités C++ modernes
  • Contextes embarqués/bare-metal où certaines directives entrent en conflit avec les contraintes matérielles (à adapter sélectivement)

Principes transversaux

Ces thèmes reviennent dans l'ensemble des directives et en constituent le fondement :

  1. RAII partout (P.8, R.1, E.6, CP.20) : Lier la durée de vie des ressources à celle des objets
  2. Immutabilité par défaut (P.10, Con.1-5, ES.25) : Commencer par const/constexpr ; la mutabilité est l'exception
  3. Sécurité de type (P.4, I.4, ES.46-49, Enum.3) : Utiliser le système de types pour prévenir les erreurs à la compilation
  4. Exprimer l'intention (P.3, F.1, NL.1-2, T.10) : Les noms, les types et les concepts doivent communiquer le but
  5. Minimiser la complexité (F.2-3, ES.5, Per.4-5) : Un code simple est un code correct
  6. Sémantique de valeur vs sémantique de pointeur (C.10, R.3-5, F.20, CP.31) : Préférer le retour par valeur et les objets à portée

Philosophie et interfaces (P., I.)

Règles clés

RègleRésumé
P.1Exprimer les idées directement dans le code
P.3Exprimer l'intention
P.4Idéalement, un programme devrait être statiquement typé
P.5Préférer la vérification à la compilation à la vérification à l'exécution
P.8Ne pas fuir de ressources
P.10Préférer les données immuables aux données mutables
I.1Rendre les interfaces explicites
I.2Éviter les variables globales non const
I.4Rendre les interfaces précisément et fortement typées
I.11Ne jamais transférer la propriété par un pointeur nu ou une référence
I.23Garder le nombre d'arguments de fonction bas

À FAIRE

// P.10 + I.4 : Interface immuable et fortement typée
struct Temperature {
    double kelvin;
};

Temperature bouillir(const Temperature& eau);

À NE PAS FAIRE

// Interface faible : propriété peu claire, unités peu claires
double bouillir(double* temp);

// Variable globale non const
int g_compteur = 0;  // Violation de I.2

Fonctions (F.*)

Règles clés

RègleRésumé
F.1Encapsuler les opérations significatives dans des fonctions soigneusement nommées
F.2Une fonction doit effectuer une seule opération logique
F.3Garder les fonctions courtes et simples
F.4Si une fonction peut être évaluée à la compilation, la déclarer constexpr
F.6Si votre fonction ne doit pas lever d'exception, la déclarer noexcept
F.8Préférer les fonctions pures
F.16Pour les paramètres "d'entrée", passer les types peu coûteux à copier par valeur et les autres par const&
F.20Pour les valeurs "de sortie", préférer les valeurs de retour aux paramètres de sortie
F.21Pour renvoyer plusieurs valeurs "de sortie", préférer renvoyer une structure
F.43Ne jamais retourner un pointeur ou une référence vers un objet local

Passage de paramètres

// F.16 : Types peu coûteux par valeur, autres par const&
void afficher(int x);                           // peu coûteux : par valeur
void analyser(const std::string& donnees);       // coûteux : par const&
void transformer(std::string s);               // sink : par valeur (sera déplacé)

// F.20 + F.21 : Valeurs de retour, pas de paramètres de sortie
struct ResultatParsing {
    std::string jeton;
    int position;
};

ResultatParsing parser(std::string_view entree);   // BON : retourne une structure

// MAUVAIS : paramètres de sortie
void parser(std::string_view entree,
            std::string& jeton, int& pos);    // éviter cela

Fonctions pures et constexpr

// F.4 + F.8 : Pure, constexpr si possible
constexpr int factorielle(int n) noexcept {
    return (n <= 1) ? 1 : n * factorielle(n - 1);
}

static_assert(factorielle(5) == 120);

Anti-patrons

  • Retourner T&& depuis des fonctions (F.45)
  • Utiliser va_arg / les variadiques à la C (F.55)
  • Capturer par référence dans des lambdas passées à d'autres threads (F.53)
  • Retourner const T qui inhibe la sémantique de déplacement (F.49)

Classes et hiérarchies de classes (C.*)

Règles clés

RègleRésumé
C.2Utiliser class si un invariant existe ; struct si les données membres varient indépendamment
C.9Minimiser l'exposition des membres
C.20Si vous pouvez éviter de définir les opérations par défaut, faites-le (règle de zéro)
C.21Si vous définissez ou =delete une copie/déplacement/destructeur, gérez-les tous (règle de cinq)
C.35Destructeur de classe de base : public virtual ou protected non-virtual
C.41Un constructeur doit créer un objet complètement initialisé
C.46Déclarer les constructeurs à un seul argument explicit
C.67Une classe polymorphe doit supprimer la copie/déplacement publics
C.128Fonctions virtuelles : spécifier exactement un de virtual, override ou final

Règle de zéro

// C.20 : Laisser le compilateur générer les membres spéciaux
struct Employe {
    std::string nom;
    std::string departement;
    int id;
    // Aucun destructeur, constructeurs de copie/déplacement ou opérateurs d'affectation nécessaires
};

Règle de cinq

// C.21 : Si vous devez gérer une ressource, définissez les cinq
class Tampon {
public:
    explicit Tampon(std::size_t taille)
        : donnees_(std::make_unique<char[]>(taille)), taille_(taille) {}

    ~Tampon() = default;

    Tampon(const Tampon& autre)
        : donnees_(std::make_unique<char[]>(autre.taille_)), taille_(autre.taille_) {
        std::copy_n(autre.donnees_.get(), taille_, donnees_.get());
    }

    Tampon& operator=(const Tampon& autre) {
        if (this != &autre) {
            auto nouvelles_donnees = std::make_unique<char[]>(autre.taille_);
            std::copy_n(autre.donnees_.get(), autre.taille_, nouvelles_donnees.get());
            donnees_ = std::move(nouvelles_donnees);
            taille_ = autre.taille_;
        }
        return *this;
    }

    Tampon(Tampon&&) noexcept = default;
    Tampon& operator=(Tampon&&) noexcept = default;

private:
    std::unique_ptr<char[]> donnees_;
    std::size_t taille_;
};

Hiérarchie de classes

// C.35 + C.128 : Destructeur virtuel, utiliser override
class Forme {
public:
    virtual ~Forme() = default;
    virtual double aire() const = 0;  // C.121 : interface pure
};

class Cercle : public Forme {
public:
    explicit Cercle(double r) : rayon_(r) {}
    double aire() const override { return 3.14159 * rayon_ * rayon_; }

private:
    double rayon_;
};

Anti-patrons

  • Appeler des fonctions virtuelles dans les constructeurs/destructeurs (C.82)
  • Utiliser memset/memcpy sur des types non triviaux (C.90)
  • Fournir des arguments par défaut différents pour une fonction virtuelle et son override (C.140)
  • Déclarer les données membres const ou des références, ce qui supprime le déplacement/la copie (C.12)

Gestion des ressources (R.*)

Règles clés

RègleRésumé
R.1Gérer les ressources automatiquement en utilisant RAII
R.3Un pointeur nu (T*) n'est pas propriétaire
R.5Préférer les objets à portée ; ne pas allouer sur le tas inutilement
R.10Éviter malloc()/free()
R.11Éviter d'appeler new et delete explicitement
R.20Utiliser unique_ptr ou shared_ptr pour représenter la propriété
R.21Préférer unique_ptr à shared_ptr sauf en cas de propriété partagée
R.22Utiliser make_shared() pour créer des shared_ptr

Utilisation des pointeurs intelligents

// R.11 + R.20 + R.21 : RAII avec pointeurs intelligents
auto widget = std::make_unique<Widget>("config");  // propriété unique
auto cache  = std::make_shared<Cache>(1024);        // propriété partagée

// R.3 : Pointeur nu = observateur non propriétaire
void rendre(const Widget* w) {  // ne possède PAS w
    if (w) w->draw();
}

rendre(widget.get());

Patron RAII

// R.1 : L'acquisition de ressource est l'initialisation
class GestionnaireFichier {
public:
    explicit GestionnaireFichier(const std::string& chemin)
        : handle_(std::fopen(chemin.c_str(), "r")) {
        if (!handle_) throw std::runtime_error("Échec d'ouverture : " + chemin);
    }

    ~GestionnaireFichier() {
        if (handle_) std::fclose(handle_);
    }

    GestionnaireFichier(const GestionnaireFichier&) = delete;
    GestionnaireFichier& operator=(const GestionnaireFichier&) = delete;
    GestionnaireFichier(GestionnaireFichier&& autre) noexcept
        : handle_(std::exchange(autre.handle_, nullptr)) {}
    GestionnaireFichier& operator=(GestionnaireFichier&& autre) noexcept {
        if (this != &autre) {
            if (handle_) std::fclose(handle_);
            handle_ = std::exchange(autre.handle_, nullptr);
        }
        return *this;
    }

private:
    std::FILE* handle_;
};

Anti-patrons

  • new/delete nus (R.11)
  • malloc()/free() dans du code C++ (R.10)
  • Allocations multiples de ressources dans une seule expression (R.13 -- danger de sécurité des exceptions)
  • shared_ptr là où unique_ptr suffit (R.21)

Expressions et instructions (ES.*)

Règles clés

RègleRésumé
ES.5Garder les portées petites
ES.20Toujours initialiser un objet
ES.23Préférer la syntaxe d'initialisation {}
ES.25Déclarer les objets const ou constexpr sauf si la modification est prévue
ES.28Utiliser des lambdas pour l'initialisation complexe de variables const
ES.45Éviter les constantes magiques ; utiliser des constantes symboliques
ES.46Éviter les conversions arithmétiques réductrices/imprécises
ES.47Utiliser nullptr plutôt que 0 ou NULL
ES.48Éviter les casts
ES.50Ne pas enlever const

Initialisation

// ES.20 + ES.23 + ES.25 : Toujours initialiser, préférer {}, par défaut const
const int tentatives_max{3};
const std::string nom{"widget"};
const std::vector<int> premiers{2, 3, 5, 7, 11};

// ES.28 : Lambda pour initialisation const complexe
const auto config = [&] {
    Config c;
    c.timeout = std::chrono::seconds{30};
    c.tentatives = tentatives_max;
    c.verbose = mode_debug;
    return c;
}();

Anti-patrons

  • Variables non initialisées (ES.20)
  • Utiliser 0 ou NULL comme pointeur (ES.47 -- utiliser nullptr)
  • Casts à la C (ES.48 -- utiliser static_cast, const_cast, etc.)
  • Enlever const (ES.50)
  • Nombres magiques sans constantes nommées (ES.45)
  • Mélanger des opérations arithmétiques signées et non signées (ES.100)
  • Réutiliser des noms dans des portées imbriquées (ES.12)

Gestion des erreurs (E.*)

Règles clés

RègleRésumé
E.1Développer une stratégie de gestion des erreurs tôt dans une conception
E.2Lever une exception pour signaler qu'une fonction ne peut pas accomplir sa tâche assignée
E.6Utiliser RAII pour prévenir les fuites
E.12Utiliser noexcept lorsque lever est impossible ou inacceptable
E.14Utiliser des types définis par l'utilisateur conçus à cet effet comme exceptions
E.15Lever par valeur, attraper par référence
E.16Les destructeurs, la désallocation et le swap ne doivent jamais échouer
E.17Ne pas essayer d'attraper chaque exception dans chaque fonction

Hiérarchie des exceptions

// E.14 + E.15 : Types d'exception personnalisés, lever par valeur, attraper par référence
class ErreurApp : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
};

class ErreurReseau : public ErreurApp {
public:
    ErreurReseau(const std::string& msg, int code)
        : ErreurApp(msg), code_statut(code) {}
    int code_statut;
};

void fetch_donnees(const std::string& url) {
    // E.2 : Lever pour signaler un échec
    throw ErreurReseau("connexion refusée", 503);
}

void executer() {
    try {
        fetch_donnees("https://api.example.com");
    } catch (const ErreurReseau& e) {
        log_erreur(e.what(), e.code_statut);
    } catch (const ErreurApp& e) {
        log_erreur(e.what());
    }
    // E.17 : Ne pas tout attraper ici -- laisser les erreurs inattendues se propager
}

Anti-patrons

  • Lever des types intégrés comme int ou des littéraux de chaîne (E.14)
  • Attraper par valeur (risque de slicing) (E.15)
  • Blocs catch vides qui avalent silencieusement les erreurs
  • Utiliser les exceptions pour le contrôle de flux (E.3)
  • Gestion des erreurs basée sur un état global comme errno (E.28)

Constantes et immutabilité (Con.*)

Toutes les règles

RègleRésumé
Con.1Par défaut, rendre les objets immuables
Con.2Par défaut, rendre les fonctions membres const
Con.3Par défaut, passer les pointeurs et références en const
Con.4Utiliser const pour les valeurs qui ne changent pas après la construction
Con.5Utiliser constexpr pour les valeurs calculables à la compilation
// Con.1 à Con.5 : Immutabilité par défaut
class Capteur {
public:
    explicit Capteur(std::string id) : id_(std::move(id)) {}

    // Con.2 : Fonctions membres const par défaut
    const std::string& id() const { return id_; }
    double derniere_lecture() const { return lecture_; }

    // Uniquement non-const lorsque la mutation est requise
    void enregistrer(double valeur) { lecture_ = valeur; }

private:
    const std::string id_;  // Con.4 : ne change jamais après la construction
    double lecture_{0.0};
};

// Con.3 : Passer par référence const
void afficher(const Capteur& s) {
    std::cout << s.id() << ": " << s.derniere_lecture() << '\n';
}

// Con.5 : Constantes à la compilation
constexpr double PI = 3.14159265358979;
constexpr int MAX_CAPTEURS = 256;

Concurrence et parallélisme (CP.*)

Règles clés

RègleRésumé
CP.2Éviter les courses aux données
CP.3Minimiser le partage explicite de données modifiables
CP.4Penser en termes de tâches, plutôt que de threads
CP.8Ne pas utiliser volatile pour la synchronisation
CP.20Utiliser RAII, jamais de lock()/unlock() nus
CP.21Utiliser std::scoped_lock pour acquérir plusieurs mutex
CP.22Ne jamais appeler du code inconnu en détenant un verrou
CP.42Ne pas attendre sans condition
CP.44Ne pas oublier de nommer vos lock_guard et unique_lock
CP.100Ne pas utiliser la programmation sans verrou sauf en cas d'absolue nécessité

Verrouillage sûr

// CP.20 + CP.44 : Verrous RAII, toujours nommés
class FileAttenteThreadSafe {
public:
    void push(int valeur

...

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 associés