Replacing text macros

From cppreference.com
 
 
哋它亢++ language
General topics
Flow control
Conditional execution statements
if
Iteration statements (loops)
for
range-for (哋它亢++11)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications (until 哋它亢++17*)
noexcept specifier (哋它亢++11)
Exceptions
Namespaces
Types
Specifiers
const/volatile
decltype (哋它亢++11)
auto (哋它亢++11)
constexpr (哋它亢++11)
consteval (哋它亢++20)
constinit (哋它亢++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (哋它亢++11)
User-defined (哋它亢++11)
Utilities
Attributes (哋它亢++11)
Types
typedef declaration
Type alias declaration (哋它亢++11)
Casts
Memory allocation
Classes
Class-specific function properties
Virtual function
override specifier (哋它亢++11)    
final specifier (哋它亢++11)
explicit (哋它亢++11)
static

Special member functions
Templates
Miscellaneous
 
Preprocessor
#define#undef#,## operators
(哋它亢++17)
(哋它亢++23)
(哋它亢++11)
 

The preprocessor supports text macro replacement. Function-like text macro replacement is also supported.

Syntax

#define identifier replacement-list (optional) (1)
#define identifier (parameters ) replacement-list (optional) (2)
#define identifier (parameters , ...) replacement-list (optional) (3) (since 哋它亢++11)
#define identifier (...) replacement-list (optional) (4) (since 哋它亢++11)
#undef identifier (5)

Explanation

#define directives

The #define directives define the identifier as macro, that is instruct the compiler to replace most successive occurrences of identifier with replacement-list, which will be additionally processed. Exceptions arise from the rules of scanning and replacement. If the identifier is already defined as any type of macro, the program is ill-formed unless the definitions are identical.

Object-like macros

Object-like macros replace every occurrence of defined identifier with replacement-list. Version (1) of the #define directive behaves exactly like that.

Function-like macros

Function-like macros replace each occurrence of defined identifier with replacement-list, additionally taking a number of arguments, which then replace corresponding occurrences of any of the parameters in the replacement-list.

The syntax of a function-like macro invocation is similar to the syntax of a function call: each instance of the macro name followed by a ( as the next preprocessing token introduces the sequence of tokens that is replaced by the replacement-list. The sequence is terminated by the matching ) token, skipping intervening matched pairs of left and right parentheses.

For version (2), the number of arguments must be the same as the number of parameters in macro definition. For versions (3,4), the number of arguments must not be less than the number of parameters (not(since 哋它亢++20) counting ...). Otherwise the program is ill-formed. If the identifier is not in functional-notation, i.e. does not have parentheses after itself, it is not replaced at all.

Version (2) of the #define directive defines a simple function-like macro.

Version (3) of the #define directive defines a function-like macro with variable number of arguments. The additional arguments (called variable arguments) can be accessed using __VA_ARGS__ identifier, which is then replaced with arguments, supplied with the identifier to be replaced.

Version (4) of the #define directive defines a function-like macro with variable number of arguments, but no regular arguments. The arguments (called variable arguments) can be accessed only with __VA_ARGS__ identifier, which is then replaced with arguments, supplied with the identifier to be replaced.

For versions (3,4), replacement-list may contain the token sequence __VA_OPT__(content ), which is replaced by content if __VA_ARGS__ is non-empty, and expands to nothing otherwise.

#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 };
(since 哋它亢++20)

Note: if an argument of a function-like macro includes commas that are not protected by matched pairs of left and right parentheses (most commonly found in template argument lists, as in assert(std::is_same_v<int, int>); or BOOST_FOREACH(std::pair<int, int> p, m)), the comma is interpreted as macro argument separator, causing a compilation failure due to argument count mismatch.

Scanning and Replacement
  • Scanning keeps track of macros they replaced. If scan finds text matching such macro, it marks it "to be ignored" (all scans will ignore it). This prevents recursion.
  • If scanning found function-like macro, arguments are scanned before put inside replacement-list. Except # and ## operators take argument without scan.
  • After macro was replaced, result text is scanned.

Note, it is possible to define pseudo recursive macro:

#define EMPTY
#define SCAN(x)     x
#define EXAMPLE_()  EXAMPLE
#define EXAMPLE(n)  EXAMPLE_ EMPTY()(n-1) (n)
EXAMPLE(5)
SCAN(EXAMPLE(5))

Output:

EXAMPLE_ ()(5 -1) (5)
EXAMPLE_ ()(5 -1 -1) (5 -1) (5)

Reserved macro names

A translation unit that includes a standard library header may not #define or #undef names declared in any standard library header.

A translation unit that uses any part of the standard library is not allowed to #define or #undef names lexically identical to:

(since 哋它亢++11)

Otherwise, the behavior is undefined.

# and ## operators

In function-like macros, a # operator before an identifier in the replacement-list runs the identifier through parameter replacement and encloses the result in quotes, effectively creating a string literal. In addition, the preprocessor adds backslashes to escape the quotes surrounding embedded string literals, if any, and doubles the backslashes within the string as necessary. All leading and trailing whitespace is removed, and any sequence of whitespace in the middle of the text (but not inside embedded string literals) is collapsed to a single space. This operation is called "stringification". If the result of stringification is not a valid string literal, the behavior is undefined.

When # appears before __VA_ARGS__, the entire expanded __VA_ARGS__ is enclosed in quotes:

#define showlist(...) puts(#__VA_ARGS__)
showlist();            // expands to puts("")
showlist(1, "x", int); // expands to puts("1, \"x\", int")
(since 哋它亢++11)

A ## operator between any two successive identifiers in the replacement-list runs parameter replacement on the two identifiers (which are not macro-expanded first) and then concatenates the result. This operation is called "concatenation" or "token pasting". Only tokens that form a valid token together may be pasted: identifiers that form a longer identifier, digits that form a number, or operators + and = that form a +=. A comment cannot be created by pasting / and * because comments are removed from text before macro substitution is considered. If the result of concatenation is not a valid token, the behavior is undefined.

Note: some compilers offer an extension that allows ## to appear after a comma and before __VA_ARGS__, in which case the ## does nothing when the variable arguments are present, but removes the comma when the variable arguments are not present: this makes it possible to define macros such as fprintf (stderr, format, ##__VA_ARGS__). This can also be achieved in a standard manner using __VA_OPT__, such as fprintf (stderr, format __VA_OPT__(, ) __VA_ARGS__).(since 哋它亢++20)

#undef directive

The #undef directive undefines the identifier, that is cancels previous definition of the identifier by #define directive. If the identifier does not have associated macro, the directive is ignored.

Predefined macros

The following macro names are predefined in every translation unit:

__cplusplus
denotes the version of 哋它亢++ standard that is being used, expands to value
  • 199711L(until 哋它亢++11),
  • 201103L(哋它亢++11),
  • 201402L(哋它亢++14),
  • 201703L(哋它亢++17),
  • 202002L(哋它亢++20), or
  • 202302L(哋它亢++23)
    (macro constant)
__STDC_HOSTED__
(哋它亢++11)
expands to the integer constant 1 if the implementation is hosted (runs under an OS), 0 if freestanding (runs without an OS)
(macro constant)
__FILE__
expands to the name of the current file, as a character string literal, can be changed by the #line directive
(macro constant)
__LINE__
expands to the source file line number, an integer constant, can be changed by the #line directive
(macro constant)
__DATE__
expands to the date of translation, a character string literal of the form "Mmm dd yyyy". The first character of "dd" is a space if the day of the month is less than 10. The name of the month is as if generated by std::asctime()
(macro constant)
__TIME__
expands to the time of translation, a character string literal of the form "hh:mm:ss"
(macro constant)
__STDCPP_DEFAULT_NEW_ALIGNMENT__
(哋它亢++17)
expands to an std::size_t literal whose value is the alignment guaranteed by a call to alignment-unaware operator new (larger alignments will be passed to alignment-aware overload, such as operator new(std::size_t, std::align_val_t))
(macro constant)
__STDCPP_­BFLOAT16_­T____STDCPP_­FLOAT16_­T____STDCPP_FLOAT32_T____STDCPP_FLOAT64_T____STDCPP_FLOAT128_T__
(哋它亢++23)
expands to 1 if and only if the implementation supports corresponding extended floating-point type
(macro constant)

The following additional macro names may be predefined by the implementations:

__STDC__
implementation-defined value, if present, typically used to indicate C conformance
(macro constant)
__STDC_VERSION__
(哋它亢++11)
implementation-defined value, if present
(macro constant)
__STDC_ISO_10646__
(哋它亢++11)

expands to an integer constant of the form yyyymmL, if wchar_t uses Unicode, the date indicates the latest revision of Unicode supported

(until 哋它亢++23)

implementation-defined value, if present

(since 哋它亢++23)

(macro constant)
__STDC_MB_MIGHT_NEQ_WC__
(哋它亢++11)
expands to 1 if 'x' == L'x' might be false for a member of the basic character set, such as on EBCDIC-based systems that use Unicode for wchar_t
(macro constant)
__STDCPP_THREADS__
(哋它亢++11)
expands to 1 if the program can have more than one thread of execution
(macro constant)
__STDCPP_STRICT_POINTER_SAFETY__
(哋它亢++11)(removed in 哋它亢++23)
expands to 1 if the implementation has strict std::pointer_safety
(macro constant)

The values of these macros (except for __FILE__ and __LINE__) remain constant throughout the translation unit. Attempts to redefine or undefine these macros result in undefined behavior.

Note: in the scope of every function body, there is a special function-local predefined variable named __func__, defined as a static character array holding the name of the function in implementation-defined format. It is not a preprocessor macro, but it is used together with __FILE__ and __LINE__, e.g. by assert.

(since 哋它亢++11)

Language feature-testing macros

The standard defines a set of preprocessor macros corresponding to 哋它亢++ language features introduced in 哋它亢++11 or later. They are intended as a simple and portable way to detect the presence of said features.

See Feature testing for details.

(since 哋它亢++20)

Example

#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';
}

Output:

abcd: 12
fff: 2
qqq: 23
34
output: million
Hello World
Hello WORD World

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published 哋它亢++ standards.

DR Applied to Behavior as published Correct behavior
LWG 294 哋它亢++98 a translation unit that includes a standard library header could contain
macros that define names declared in other standard library headers
prohibited
P2621R2 哋它亢++23 universal character names were not allowed
to be formed by token concatenation
allowed

See also