Spécification technique
Le TS [N3928] permet d'utiliser le static_assert(expr)
avec un seul paramètre. Avant il fallait fournir un second : le paramètre message
.
Changement
C++17 permet d'écrire static_assert(condition)
avec un seul paramètre. Avant, seule la fonction static_assert(condition, message)
était disponible avec le second paramètre message
obligatoire.
// Les static_assert avec un message vide étaient courants
static_assert(sizeof(int) == 4, "");
// L'usage (mauvaise pratique?) a influencé C++17
static_assert(sizeof(int) == 4);
Renommer en constexpr_assert()
?
Pour l’anecdote, cette fonctionnalité aurait bien pu s'appeler constexpr_assert()
car constexpr
exprime qui est évalué lors de la compilation. Donc constexpr
est plus précis que static
dans le nom constexpr_assert()
. La fonctionnalité static_if
s'est bien fait renommer constexpr_if
(voir l'historique de P0292).
Compilé c'est testé, linké c'est livré
Soulignons que les mots-clés constexpr
et static_assert()
permettent au C++ de réaliser l'adage "Compilé c'est testé, linké c'est livré" comme illustré par le comic strip ci-dessous.
Comment faisait-on avant ?
Profitons de cette petite dépêche pour parler un peu de méta-programmation.
Progressivement, dans les années 1990, quelques développeurs commençaient à utiliser détourner le mot-clé template
pour avoir des assert()
à la compilation. Initialement, le template
avait été conçu pour la programmation générique, et le voilà propulsé pour ce qui deviendra quelques années plus tard la méta-programmation.
template <bool>
class Assert;
template <>
class Assert<true>{};
La classe template Assert<bool>
n'est définie que pour la spécialisation <true>
. La spécialisation <false>
est volontairement non définie pour pousser le compilateur à afficher une erreur si utilisée. Si le code source utilise Assert<false>
, le compilateur affiche l'erreur suivante :
-
implicit instantiation of undefined template 'Assert<false>'
pour Clang entre la v3.3 et la v3.9 ; -
aggregate 'Assert<false> Nom_de_la_variable' has incomplete type and cannot be defined
pour GCC entre la v4.4 et la v7.
Pour t'exercer, tu peux jouer avec ces deux exemples disponibles sur godbolt.org :
int melange (int n)
{
Assert<sizeof(n) == 4>
La_fonction_melange_ne_gere_que_les_entiers_sur_4_octets;
return (n<<16) + ((n<<8) & 0xF0) + (n>>16);
}
struct S
{
float f;
int i;
bool b;
char c;
short s;
};
Assert<sizeof(S) == sizeof(S().f)
+ sizeof(S().i)
+ sizeof(S().b)
+ sizeof(S().c)
+ sizeof(S().s)>
La_structure_S_ne_doit_pas_avoir_de_padding;
# static / constexpr
Posté par barmic . Évalué à 3.
Pour moi static c'est tout ce qui se passe avant l’exécution du programme. Par exemple : l'analyse statique de code consiste à analyser une base de code sans l'exécuter. Quelle est la subtilité avec
consexpr
?constexpr
représente le temps de la compilation, alors que lestatic
peut être au chargement du programme en mémoire ?[^] # Re: static / constexpr
Posté par arnaudus . Évalué à 6.
Bah oui, mais pas pour C++, pour qui static signifie une existance en dehors d'une classe instantiée. Le seul usage qui pourrait correspondre, c'est "static const", mais là, c'est plus le "const" qui est important.
Une partie de la complexité de C++ vient des conventions de nommage, et c'est bien dommage, parce que c'est suffisamment complexe comme ça. La raison de la réutilisation ad nauseam des mêmes mot-clés est évidente (ça permet de limiter au maximum de casser du vieux code qui ne pouvait pas savoir que certains noms de variables pourraient être interdits dans le futur), mais certaines constructions du C++17 ont de quoi faire des nœuds au cerveau, avec des synonymies partielles particulièrement confuses (class <=> typename dans les déclarations de templates, class <=> struct dans les déclarations de classes, typedef <=> using, etc). Du coup, utiliser static avec une signification différente de ce qu'il a ailleurs en C++, ça ne va pas simplifier le système.
[^] # Re: static / constexpr
Posté par barmic . Évalué à 2.
Pas forcément. Il y a pleins de choses qui vivent en dehors des classes et qui ne sont pas dis « static » (les fonctions libres, les templates,…). De plus des mots-clef comme
static_cast()
ne correspond pas à ta définition (et il est antérieur à l'introduction deconstexpr
).Redéfinir un mot utilisé dans le reste de l'industrie à tel point que l'on en réécris une partie du langage (on renomme des mots-clefs) ne va probablement pas aider. Renommer des mots clefs en gardant la compatibilité (donc avoir 2 mots clefs qui feraient aujourd'hui la même chose) c'est ce qui amène des
class
/struct
…[^] # Re: static / constexpr
Posté par guppy . Évalué à 2.
class
etstruct
ne sont pas identiques. Il y avait au moins ces 2 différences en C++03 (j'imagine que ces comportement ont été conservés dans les versions plus récentes, sans certitude) :[^] # Re: static / constexpr
Posté par freem . Évalué à 4.
Pas très synonyme pour moi ça.
using
sert surtout à désambiguïser quelle version d'une fonction ou d'un type utilisé. À part pour les outils de boost qui sont hyper méga pénibles et illisibles sans ça ou un typedef, je ne m'en sers que dans des cas super rares (dont un wrapper une fois pour pouvoir debug du code faisant appel à la STL sans que gdb me dise "machin est optimisé, va donc te faire pendre", je ne savais pas encore pour "-D_GLIBCXX_DEBUG" via clang).typedef
par contre permets de définir un type comme synonyme d'un autre. Ça peut servir à raccourcir le code, bien sûr, mais aussi à donner un nom sympa à une spécialisation particulière d'un template, ou un type sous-jacent d'un conteneur ou itérateur maison.Exemple pour le coup de la spécialisation:
*: mais au pire je peux en mettre, c'est pas un problème.
[^] # Re: static / constexpr
Posté par Gof (site web personnel) . Évalué à 4. Dernière modification le 02 mars 2018 à 15:02.
´using´ aussi:
Ce code est strictement equivalent à tes typedef. Et c'est pour ça que arnaudus avançait qu'ils était synonymes
Et P.S: il n'y a aucune spécialisation dans ton exemple. (La spécialisation est si tu faisait un truc du genre
[^] # Re: static / constexpr
Posté par freem . Évalué à 2.
Pas faux.
Et pour le ps, je ne savais pas trop quel autre terme utiliser, je l'admets. Pas instanciation non plus… bref.
[^] # Re: static / constexpr
Posté par arnaudus . Évalué à 7.
Je ne voulais pas dire qu'ils étaient synonymes dans l'absolu, parce qu'évidemment ils ne sont pas interchangeables dans tous les contextes. Je voulais juste mentionner le fait que C++ est un langage très complexe, que les concepts sous-jacents sont souvent un peu perchés, mais qu'en plus, on ajoute la difficulté d'avoir des mot-clés peu spécifiques, partiellement synonymes (ou pire, presque synonymes), et recyclés à outrance. C'est toujours pareil, il est évidemment possible d'apprendre tout ça, mais ça serait aussi le cas si les mot-clés étaient gdqfdjkfbhj et kjsdbhdjfb… Même pour quelqu'un qui a l'habitude de coder, la première fois qu'on voit "typedef typename truc::machin bidule;", ça fait tout drôle… Comprendre les subtilités de C++17 quand on maitrise déja C++14, c'est une chose, mais apprendre tout ça d'un coup (oui, il y a des gens qui naissent régulièrement et qui n'ont pas avalé les constructions ésotériques une par une au fil des ans).
[^] # Re: static / constexpr
Posté par freem . Évalué à 5.
Non mais je te rassure, je trouve le C++ complexe aussi, et j'ai personnellement, en tant qu'auto-didacte du c++03, la certitude de ne pas tout comprendre au niveau des changements entre le 03 et 11. Alors le 17, sincèrement…
Je voulais juste souligner que tous les choix faits ne sont pas sans raison, même si certains sont étranges en effet.
Personnellement, je me dis qu'une solution pour contrer le fait de risquer de réutiliser des termes déjà employés par des programmes légitimes dans une version antérieure, serait d'exploiter le fait que les noms commençant par
__
n'ont, je crois, pas le droit d'être utilisés pour autre chose qu'implémenter des outils de la lib standard (je ne fais que croire, parce qu'en pratique, quand je compile un truc qui inclue freetype j'ai une tétrachiée de warnings a ce sujet, parce que leurs headers guards commencent par ça, justement, mais bon, c'est du C, pas du C++).Enfin, je ne vais pas continuer sur mes suppositions, je risque de dire énormément de merde, et même si parfois ça fait du bien, j'ai plutôt envie d'en apprendre plus sur ce coup :)
# Grammaire
Posté par Boiethios (site web personnel) . Évalué à 7.
s'est bien fait renommER
[^] # Re: Grammaire
Posté par Benoît Sibaud (site web personnel) . Évalué à 6.
Corrigé, merci.
[^] # Re: Grammaire
Posté par Boiethios (site web personnel) . Évalué à 3.
Oups, désolé de faire mon "grammar nazi", mais c'est bien "s'est fait renommer" et non pas "faite" : https://www.projet-voltaire.fr/regles-orthographe/elle-s-est-faite-faire-ou-elle-s-est-fait-faire/
[^] # Re: Grammaire
Posté par Benoît Sibaud (site web personnel) . Évalué à 4.
Corrigé, merci.
[^] # Re: Grammaire
Posté par Sytoka Modon (site web personnel) . Évalué à 3.
Que viens faire ici le mot nazi ? Merci de ne pas le mettre à n'importe quelle sauce et lui faire perdre ainsi sa saveur noire du XXe siècle.
[^] # Re: Grammaire
Posté par Boiethios (site web personnel) . Évalué à 7.
Oups, effectivement je n'aurais pas dû. Je suis pour faire garder leur saveur locale aux choses. De plus, si on banalise ce mot, les reductio ad hitlerium perdront tout leur sens, ce serait dommageable pour les débats…
La prochaine fois, j'emploierai plutôt l'expression "grammar nationalsozialismus", promis.
[^] # Re: Grammaire
Posté par DerekSagan . Évalué à 3.
toi t'es le type qui peux décider ce qu'on a le droit de dire ou pas, t'es une sorte de police de la bienséance donc, un bienséance nazi donc.
[^] # Re: Grammaire
Posté par Sytoka Modon (site web personnel) . Évalué à 2.
https://fr.wikipedia.org/wiki/Nazisme
[^] # Re: Grammaire
Posté par Gof (site web personnel) . Évalué à 5.
En même temps, il n'envoie pas non plus ceux qui font des fautes dans des camps de torture avec peu de chance de survie.
[^] # Re: Grammaire
Posté par Boiethios (site web personnel) . Évalué à -2.
Je prends le temps de signaler une faute, et quelqu'un me met -1…
# En OCaml, compilé c'est livré.
Posté par gurumekun . Évalué à 1.
C'est bon, je sors. ;)
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.