Replacing text macros
Le préprocesseur prend en charge le remplacement de macros textuelles. Le remplacement de macros textuelles de type fonction est également pris en charge.
Table des matières |
Syntaxe
#define
identifiant liste-de-remplacement
(optionnel)
|
(1) | ||||||||
#define
identifiant
(
paramètres
)
liste-de-remplacement
(optionnel)
|
(2) | ||||||||
#define
identifiant
(
paramètres
, ...)
liste-de-remplacement
(optionnel)
|
(3) | (depuis C++11) | |||||||
#define
identifiant
(...)
liste-de-remplacement
(optionnel)
|
(4) | (depuis C++11) | |||||||
#undef
identifiant
|
(5) | ||||||||
Explication
#define directives
Les directives #define définissent l' identifier comme macro, c'est-à-dire qu'elles indiquent au compilateur de remplacer la plupart des occurrences successives de l' identifier par la replacement-list , qui sera traitée ultérieurement. Des exceptions surviennent selon les règles de balayage et remplacement . Si l'identifiant est déjà défini comme un quelconque type de macro, le programme est mal formé sauf si les définitions sont identiques.
Macros de type objet
Les macros de type objet remplacent chaque occurrence de l' identifiant défini par la liste-de-remplacement . La version (1) de la directive #define se comporte exactement de cette manière.
Macros de type fonction
Les macros de type fonction remplacent chaque occurrence de l' identifiant défini par la liste-de-remplacement , en prenant en plus un certain nombre d'arguments qui remplacent ensuite les occurrences correspondantes de l'un des paramètres dans la liste-de-remplacement .
La syntaxe d'un appel de macro de type fonction est similaire à la syntaxe d'un appel de fonction : chaque occurrence du nom de la macro suivie d'un ( comme prochain jeton de préprocesseur introduit la séquence de jetons qui est remplacée par la replacement-list . La séquence est terminée par le jeton correspondant ) , en sautant les paires correspondantes de parenthèses gauches et droites intermédiaires.
Pour la version (2), le nombre d'arguments doit être identique au nombre de paramètres dans la définition de la macro. Pour les versions (3,4), le nombre d'arguments ne doit pas être inférieur au nombre de paramètres (
non
(depuis C++20)
comptant
...
). Sinon le programme est mal formé. Si l'identifiant n'est pas en notation fonctionnelle, c'est-à-dire s'il n'a pas de parenthèses après lui-même, il n'est pas remplacé du tout.
La version (2) de la directive #define définit une macro simple de type fonction.
La version (3) de la directive
#define
définit une macro de type fonction avec un nombre variable d'arguments. Les arguments supplémentaires (appelés
arguments variables
) peuvent être accédés en utilisant l'identifiant
__VA_ARGS__
, qui est ensuite remplacé par les arguments fournis avec l'identifiant à remplacer.
La version (4) de la directive
#define
définit une macro de type fonction avec un nombre variable d'arguments, mais sans arguments réguliers. Les arguments (appelés
arguments variables
) ne peuvent être accédés qu'avec l'identifiant
__VA_ARGS__
, qui est ensuite remplacé par les arguments fournis avec l'identifiant à remplacer.
|
Pour les versions (3,4),
replacement-list
peut contenir la séquence de tokens
#define F(...) f(0 __VA_OPT__(,) __VA_ARGS__) F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) #define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__) G(a, b, c) // replaced by f(0, a, b, c) G(a, ) // replaced by f(0, a) G(a) // replaced by f(0, a) #define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ }) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 }; |
(depuis C++20) |
Note : si un argument d'une macro de type fonction contient des virgules qui ne sont pas protégées par des paires de parenthèses gauche et droite correspondantes (le plus souvent dans les listes d'arguments de template, comme dans assert ( std:: is_same_v < int , int > ) ; ou BOOST_FOREACH ( std:: pair < int , int > p, m ) ), la virgule est interprétée comme un séparateur d'arguments de macro, provoquant une erreur de compilation due à un décompte d'arguments incorrect.
Balayage et Remplacement
- Le balayage garde trace des macros qu'elles ont remplacées. Si le balayage trouve un texte correspondant à une telle macro, il le marque "à ignorer" (tous les balayages l'ignoreront). Cela empêche la récursion.
- Si le balayage trouve une macro de type fonction, les arguments sont balayés avant d'être insérés dans la replacement-list . Sauf que les opérateurs # et ## prennent l'argument sans balayage.
- Après le remplacement de la macro, le texte résultant est balayé.
Notez qu'il est possible de définir une macro pseudo-récursive :
#define EMPTY #define SCAN(x) x #define EXAMPLE_() EXAMPLE #define EXAMPLE(n) EXAMPLE_ EMPTY()(n-1) (n) EXAMPLE(5) SCAN(EXAMPLE(5))
Sortie :
EXAMPLE_ ()(5 -1) (5) EXAMPLE_ ()(5 -1 -1) (5 -1) (5)
Noms de macros réservés
Une unité de traduction qui inclut un en-tête de bibliothèque standard ne peut pas #define ou #undef les noms déclarés dans tout en-tête de bibliothèque standard .
Une unité de traduction qui utilise une partie de la bibliothèque standard n'est pas autorisée à #define ou #undef des noms lexicalement identiques à :
|
(depuis C++11) |
Sinon, le comportement est indéfini.
# et ## opérateurs
Dans les macros de type fonction, un opérateur # placé devant un identifiant dans la replacement-list soumet cet identifiant au remplacement des paramètres et l'encadre de guillemets, créant ainsi effectivement un littéral de chaîne. De plus, le préprocesseur ajoute des barres obliques inverses pour échapper les guillemets entourant les littéraux de chaîne intégrés, le cas échéant, et double les barres obliques inverses dans la chaîne si nécessaire. Tous les espaces blancs de début et de fin sont supprimés, et toute séquence d'espaces blancs au milieu du texte (mais pas à l'intérieur des littéraux de chaîne intégrés) est réduite à un seul espace. Cette opération est appelée « stringification ». Si le résultat de la stringification n'est pas un littéral de chaîne valide, le comportement est indéfini.
|
Lorsque
#
apparaît avant
#define showlist(...) puts(#__VA_ARGS__) showlist(); // expands to puts("") showlist(1, "x", int); // expands to puts("1, \"x\", int") |
(depuis C++11) |
Un opérateur
##
entre deux identifiants successifs dans la
liste de remplacement
effectue le remplacement des paramètres sur les deux identifiants (qui ne sont pas d'abord développés en tant que macros) puis concatène le résultat. Cette opération est appelée "concaténation" ou "collage de jetons". Seuls les jetons qui forment ensemble un jeton valide peuvent être collés : des identifiants formant un identifiant plus long, des chiffres formant un nombre, ou les opérateurs
+
et
=
formant un
+=
. Un commentaire ne peut pas être créé en collant
/
et
*
car les commentaires sont supprimés du texte avant que la substitution des macros ne soit considérée. Si le résultat de la concaténation n'est pas un jeton valide, le comportement est indéfini.
Note : certains compilateurs proposent une extension qui permet à
##
d'apparaître après une virgule et avant
__VA_ARGS__
, auquel cas le
##
ne fait rien lorsque les arguments variables sont présents, mais supprime la virgule lorsque les arguments variables sont absents : cela permet de définir des macros telles que
fprintf
(
stderr
, format,
##__VA_ARGS__)
.
Cela peut également être réalisé de manière standard en utilisant
__VA_OPT__
, comme dans
fprintf
(
stderr
, format __VA_OPT__
(
,
)
__VA_ARGS__
)
.
(depuis C++20)
#undef directive
La directive #undef supprime la définition de l' identifiant , c'est-à-dire annule la définition précédente de l' identifiant par la directive #define . Si l'identifiant n'a pas de macro associée, la directive est ignorée.
Macros prédéfinies
Les noms de macro suivants sont prédéfinis dans chaque unité de traduction :
|
__cplusplus
|
désigne la version de la norme C++ utilisée, se développe en valeur
|
|
__STDC_HOSTED__
(C++11)
|
se développe en la constante entière
1
si l'implémentation est hébergée (fonctionne sous un OS),
0
si autonome (fonctionne sans OS)
(constante de macro) |
|
__FILE__
|
se développe en le nom du fichier courant, sous forme de littéral de chaîne de caractères, peut être modifié par la directive
#line
(constante de macro) |
|
__LINE__
|
se développe en le numéro de ligne du
fichier source physique courant
, une constante entière, peut être modifié par la directive
#line
(constante de macro) |
|
__DATE__
|
se développe en la date de traduction, un littéral de chaîne de caractères de la forme
"Mmm dd yyyy"
. Le premier caractère de
"dd"
est un espace si le jour du mois est inférieur à 10. Le nom du mois est comme généré par
std::
asctime
(
)
(constante de macro) |
|
__TIME__
|
se développe en l'heure de traduction, un littéral de chaîne de caractères de la forme
"hh:mm:ss"
(constante de macro) |
|
__STDCPP_DEFAULT_NEW_ALIGNMENT__
(C++17)
|
se développe en un littéral
std::size_t
dont la valeur est l'alignement garanti par un appel à l'
operator new
non-aligné (les alignements plus grands seront passés aux surcharges alignées, telles que
operator new
(
std::
size_t
,
std::
align_val_t
)
)
(constante de macro) |
|
__STDCPP_BFLOAT16_T__
__STDCPP_FLOAT16_T__
__STDCPP_FLOAT32_T__
__STDCPP_FLOAT64_T__
__STDCPP_FLOAT128_T__
(C++23)
|
se développe en
1
si et seulement si l'implémentation prend en charge le
type flottant étendu
correspondant
(constante de macro) |
|
__STDC_EMBED_NOT_FOUND__
__STDC_EMBED_FOUND__
__STDC_EMBED_EMPTY__
(C++26)
|
se développe respectivement en
0
,
1
et
2
(constante de macro) |
Les noms de macros supplémentaires suivants peuvent être prédéfinis par les implémentations :
|
__STDC__
|
valeur définie par l'implémentation, si présente, généralement utilisée pour indiquer la conformité C
(constante macro) |
||||
|
__STDC_VERSION__
(C++11)
|
valeur définie par l'implémentation, si présente
(constante macro) |
||||
|
__STDC_ISO_10646__
(C++11)
|
(constante macro) |
||||
|
__STDC_MB_MIGHT_NEQ_WC__
(C++11)
|
s'étend en
1
si
'x'
==
L
'x'
peut être faux pour un membre
x
du jeu de caractères de base, comme sur les systèmes basés sur EBCDIC qui utilisent Unicode pour
wchar_t
(constante macro) |
||||
|
__STDCPP_THREADS__
(C++11)
|
s'étend en
1
si le programme peut avoir plus d'un thread d'exécution
(constante macro) |
|
__STDCPP_STRICT_POINTER_SAFETY__
(C++11)
(supprimé en C++23)
|
s'étend à
1
si l'implémentation a une sécurité de pointeur stricte
std::pointer_safety
(constante macro) |
Les valeurs de ces macros (à l'exception de
__FILE__
et
__LINE__
) restent constantes tout au long de l'unité de traduction. Toute tentative de redéfinir ou de supprimer ces macros entraîne un comportement indéfini.
Macros de test de fonctionnalités du langageLa norme définit un ensemble de macros de préprocesseur correspondant aux fonctionnalités du langage C++ introduites dans C++11 ou ultérieur. Elles sont conçues comme un moyen simple et portable de détecter la présence desdites fonctionnalités. Voir Test de fonctionnalités pour plus de détails. |
(depuis C++20) |
NotesLa variable prédéfinie locale à la fonction __func__ n'est pas une macro prédéfinie, mais elle est généralement utilisée conjointement avec __FILE__ et __LINE__ , par exemple par assert . |
(depuis C++11) |
Exemple
#include <iostream> // Make function factory and use it #define FUNCTION(name, a) int fun_##name() { return a; } FUNCTION(abcd, 12) FUNCTION(fff, 2) FUNCTION(qqq, 23) #undef FUNCTION #define FUNCTION 34 #define OUTPUT(a) std::cout << "output: " #a << '\n' // Using a macro in the definition of a later macro #define WORD "Hello " #define OUTER(...) WORD #__VA_ARGS__ int main() { std::cout << "abcd: " << fun_abcd() << '\n'; std::cout << "fff: " << fun_fff() << '\n'; std::cout << "qqq: " << fun_qqq() << '\n'; std::cout << FUNCTION << '\n'; OUTPUT(million); //note the lack of quotes std::cout << OUTER(World) << '\n'; std::cout << OUTER(WORD World) << '\n'; }
Sortie :
abcd: 12 fff: 2 qqq: 23 34 output: million Hello World Hello WORD World
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Applicable à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| CWG 2908 | C++98 |
il n'était pas clair si
__LINE__
se développe en le numéro
de ligne physique actuel ou le numéro de ligne logique actuel |
se développe en le numéro
de ligne physique actuel |
| LWG 294 | C++98 |
une unité de traduction incluant un en-tête de bibliothèque standard pouvait contenir
des macros définissant des noms déclarés dans d'autres en-têtes de bibliothèque standard |
interdit |
| P2621R2 | C++23 |
les noms de caractères universels n'étaient pas autorisés
à être formés par concaténation de jetons |
autorisé |
Voir aussi
|
Documentation C++
pour
Index des symboles de macro
|
|
|
Documentation C
pour
Remplacement des macros de texte
|