Présentation
Le standard C++26 ajoute une syntaxe native pour exprimer des préconditions et des postconditions directement dans la déclaration ou la définition d’une fonction. Cette fonctionnalité, issue de la proposition P2900, se distingue de l’usage classique de assert en rendant les exigences visibles au moment de la lecture de l’API, sans nécessiter l’accès au corps de la fonction.
Mécanisme des contracts
La syntaxe s’appuie sur le mot‑clé pre placé après la liste des paramètres :
int get_value(const std::vector& values, std::size_t index)
pre(index < values.size())
{
return values[index];
}Le même pre peut être ajouté à la déclaration uniquement, ce qui permet à tout utilisateur du header de connaître la contrainte index < values.size() sans consulter l’implémentation. Les postconditions utilisent le mot‑clé post de façon analogue, séparant clairement ce que l’appelant doit garantir de ce que la fonction promet de retourner.
Semantiques d'évaluation et compilation
C++26 définit quatre semantiques d’évaluation : ignore (aucune vérification), observe (signalement sans arrêt), enforce (termination ou appel d’un gestionnaire) et un quatrième non nommé dans l’article mais présent dans la spécification. Le compilateur choisit la semantique appliquée à chaque assertion contractuelle. Sous GCC 16, disponible dès octobre 2026, on active les contracts avec les options suivantes :
g++ -std=c++26 -fcontracts=enforce example.cppAvec enforce, une violation déclenche le gestionnaire par défaut qui émet un diagnostic détaillé : nom de la fonction, fichier, ligne et texte de la condition. Le développeur peut remplacer ce gestionnaire en incluant <contracts> et en définissant une fonction de rappel :
#include
#include
void handle_contract_violation(const std::contracts::contract_violation& v) {
std::println(stderr, "Contract violated: {}", v.comment());
}Le gestionnaire reçoit un objet std::contracts::contract_violation contenant le prédicat, la localisation et la semantique utilisée, ce qui facilite le logging ou la collecte de métriques d’erreur.
Implications et limites
Les contracts ne font pas partie du type de fonction ; ils n’influencent donc pas la résolution de surcharge. Cette séparation garantit que les appels restent compatibles même si les exigences contractuelles évoluent, à condition que les nouvelles contraintes ne soient pas plus strictes que les précédentes. En revanche, la première déclaration d’une fonction fixe l’ensemble des pré‑ et postconditions ; toute déclaration ultérieure doit répéter exactement les mêmes assertions ou les omettre, mais ne peut en introduire de nouvelles. Enfin, la portabilité reste limitée : à ce jour seul GCC 16 implémente pleinement les contracts, les autres compilateurs n’offrent pas encore de support complet, ce qui contraint les projets multiplateformes à recourir à des solutions de repli comme les assert classiques.