Pour ceux d'entre vous qui veulent quelque chose de vraiment basique et portable mais qui n'ont pas accès aux fonctionnalités du C++11, j'ai écrit exactement ce qu'il faut.
Utilisez STATIC_ASSERT
normalement (vous pouvez l'écrire deux fois dans la même fonction si vous le souhaitez) et utiliser la fonction GLOBAL_STATIC_ASSERT
en dehors des fonctions avec une phrase unique comme premier paramètre.
#if defined(static_assert)
# define STATIC_ASSERT static_assert
# define GLOBAL_STATIC_ASSERT(a, b, c) static_assert(b, c)
#else
# define STATIC_ASSERT(pred, explanation); {char assert[1/(pred)];(void)assert;}
# define GLOBAL_STATIC_ASSERT(unique, pred, explanation); namespace ASSERTATION {char unique[1/(pred)];}
#endif
GLOBAL_STATIC_ASSERT(first, 1, "Hi");
GLOBAL_STATIC_ASSERT(second, 1, "Hi");
int main(int c, char** v) {
(void)c; (void)v;
STATIC_ASSERT(1 > 0, "yo");
STATIC_ASSERT(1 > 0, "yo");
// STATIC_ASSERT(1 > 2, "yo"); //would compile until you uncomment this one
return 0;
}
Explication :
Tout d'abord, il vérifie si vous disposez de l'affirmation réelle, que vous devez absolument utiliser si elle est disponible.<br>Si vous ne le faites pas, il affirme en obtenant votre <code>pred</code> icate, et en le divisant par lui-même. Cela fait deux choses.<br>S'il est égal à zéro, c'est-à-dire que l'assertion a échoué, elle provoquera une erreur de division par zéro (l'arithmétique est forcée car elle essaie de déclarer un tableau).<br>Si elle n'est pas nulle, elle normalise la taille du tableau à <code>1</code> . Donc, si l'assertion a réussi, vous ne voudriez pas qu'elle échoue de toute façon parce que votre prédicat a été évalué à <code>-1</code> (invalide), ou être <code>232442</code> (gaspillage massif d'espace, je ne sais pas si cela peut être optimisé).<br>Pour <code>STATIC_ASSERT</code> il est entouré d'accolades, ce qui en fait un bloc, qui détermine la portée de la variable <code>assert</code> ce qui signifie que vous pouvez l'écrire plusieurs fois.<br>Il le lance aussi à <code>void</code> ce qui est un moyen connu pour se débarrasser de <code>unused variable</code> avertissements.<br>Pour <code>GLOBAL_STATIC_ASSERT</code> au lieu d'être dans un bloc de code, il génère un espace de nom. Les espaces de noms sont autorisés en dehors des fonctions. A <code>unique</code> est nécessaire pour éviter tout conflit de définitions si vous utilisez celui-ci plus d'une fois.
Cela a fonctionné pour moi avec GCC et VS'12 C++.
0 votes
Pour C11 sur GCC/Clang pour le contrôle d'égalité avec int32_ts, vous pouvez même faire en sorte que le compilateur imprime la valeur incorrecte s'il échoue ! stackoverflow.com/q/53310844/1495449