I. Attributs en C++11▲
Voilà qui a changé avec le C++11 : les attributs sont désormais portables en les écrivant entre doubles crochets :
[[xyz]]
void
foo(int
i, int
j) {
//...
}
Malheureusement, ça ne résout pas le problème général : seuls quelques attributs sont standardisés.
Les compilateurs sont toujours autorisés à utiliser leurs propres attributs, mais ils doivent se situer dans leur espace de nom. Par exemple, l’attribut fastcall de GCC peut s’écrire de façon standard : [[gnu::fastcall]]
, et les autres compilateurs ne sont pas tenus de le comprendre.
Jusqu’à C++17, les autres compilateurs peuvent même refuser la compilation en rencontrant un attribut inconnu. Depuis C++17, ils doivent les ignorer. Il semble cependant que MSVC 2015 ne supporte pas du tout la nouvelle syntaxe des attributs…
II. Attributs standards▲
Conformité des compilateurs au standard mise à part, certains attributs ont été standardisés.
Voici les plus importants pour la maintenabilité :
-
[[deprecated]]
,[[deprecated(
"Because it's old"
)]]
Cet attribut permet de marquer des fonctions, variables, classes… qui ne doivent plus être utilisées, car elles seront retirées du code à l’avenir.
Déprécier des éléments de la sorte peut être particulièrement pratique si l’on est en train de nettoyer un code, mais que les retirer purement et simplement n’est pas faisable à cause de leur couplage fort avec l’existant. -
[[fallthrough]]
Cet attribut à la fin d’uncase
dans unswitch
signale que le mot-clébreak
a été volontairement omis. Sans ça, les analyseurs statiques et les relecteurs pourraient alerter sur lebreak
manquant : cela précise à tout le monde que vous savez ce que vous faites.Sélectionnezswitch
(something){
case
SPECIAL_CASE: prepareForSpecialCase();[[fallthrough]]
default
:
handleAllCases();}
-
[[nodiscard]]
Cet attribut demande au compilateur d’avertir si, lors de l’appel d’une fonction qui possède l’attribut, ou dont le type de retour le possède, la valeur de retour est ignorée. Une valeur de retour est ignorée quand elle n’est pas affectée à une variable : elle est typiquement appelée comme simple expression, ou à gauche d’un opérateur virgule. L’avertissement peut être supprimé avec un cast explicite de la valeur envoid
.Sélectionnezstruct
[[nodiscard]]
X{
int
i;}
; X foo(){
return
{
42
}
;}
[[nodiscard]]
int
bar(){
return
3
;}
void
moo(){
foo();//Warning: discarded X
auto
i=
(bar(),55
);//Warning: discarded bar()
(void
)bar();//OK
}
-
[[maybe_unused]]
En pratique l’inverse de[[nodiscard]]
: de nombreux compilateurs avertissent déjà des valeurs non usitées dans certains cas.[[maybe_unused]]
supprime cet avertissement sur celles déclarées avec cet attribut. -
[[noreturn]]
S’applique uniquement aux déclarations de fonctions, et précise que la fonction ne retournera pas ; c.-à-d. que la fonction soit lancera une exception, soit appellera exit ou terminate dans toutes ses branches d’exécution. Principalement utilisé pour l’optimisation, il tient aussi lieu d’un peu de documentation.
III. Conclusion▲
L’implémentation des attributs, tout comme leur standardisation, sont loin d’être terminées et suivent leur cours.
Ce qui existe déjà peut être utile et devrait être utilisé à bon escient.
Pour plus d’informations sur les attributs, je vous recommande ce billet de Bartlomiej Filipek !
IV. Remerciements▲
Nous remercions Arne Mertz qui nous a aimablement autorisés à traduire ce tutoriel. Nos remerciements également à MaximeCh pour la traduction, Winjerome et Luc Hermitte pour la relecture technique et la mise au gabarit DVP, f-leb pour la correction orthographique.