Namespaces
Variants

Replacing text macros

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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 __VA_OPT__( content  ) , qui est remplacée par content si __VA_ARGS__ n'est pas vide, et se développe en rien sinon.

#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 __VA_ARGS__ , l'intégralité de l'expansion de __VA_ARGS__ est placée entre guillemets :

#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
  • 199711L (jusqu'à C++11) ,
  • 201103L (C++11) ,
  • 201402L (C++14) ,
  • 201703L (C++17) ,
  • 202002L (C++20) , ou
  • 202302L (C++23)
    (constante de macro)
__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)

s'étend en une constante entière de la forme yyyymmL , si wchar_t utilise Unicode, la date indique la dernière révision d'Unicode prise en charge

(jusqu'à C++23)

valeur définie par l'implémentation, si présente

(depuis C++23)

(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 langage

La 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)


Notes

La 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