Replacing text macros
From Cppreference
C++ Standard Library |
---|
C++ language |
Preprocessor |
The preprocessor supports text macro replacement. Function-like text macro replacement is also supported.
Contents |
[edit] Syntax
#define identifier replacement-list | (1) | ||||||||
#define identifier( parameters ) replacement-list | (2) | ||||||||
#define identifier( parameters, ... ) replacement-list | (3) | ||||||||
#define identifier( ... ) replacement-list | (4) | ||||||||
#undef identifier | (5) | ||||||||
[edit] Explanation
[edit] #define directives
The #define directives define the identifier as macro, that is instruct the compiler to replace all successive occurrences of identifier with replacement-list, which can be optionally additionally processed. If the identifier is already defined as any type of macro, the program is ill-formed.
[edit] 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.
[edit] 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 number of arguments must be the same as the number of arguments in macro definition (parameters) or 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 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 can be accessed only with __VA_ARGS__ identifier, which is then replaced with arguments, supplied with identifier to be replaced.
[edit] # and ## operators
An # operator before an identifier in the replacement-list of function-like macro puts in quotes the text, resulting from the identifier after the parameter replacement step.
An ## operator between any two successive identifiers in the replacement-list concatenates two pieces of text, resulting from the identifiers after the parameter replacement step.
[edit] #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.
[edit] Predefined macros
The following macro names are predefined in any translation unit.
__cplusplus |
expands to value 199711L(until C++11) or 201103L(since C++11) (macro constant) |
__STDC_HOSTED__
(C++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 (macro constant) |
__LINE__ |
expands to the source file line number, an integer constant (macro constant) |
__DATE__ |
expands to the date of translation, a character string literal of the form "Mmm dd yyyy". 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) |
The following additional macro names may be predefined by the implementations.
__STDC__ |
implementation-defined value, if present (macro constant) |
__STDC_VERSION__
(C++11)
|
implementation-defined value, if present (macro constant) |
__STDC_ISO_10646__
(C++11)
|
expands to an integer constant of the form yyyymmL, if wchar_t uses Unicode, the date indicates the latest revision of Unicode supported (macro constant) |
__STDC_MB_MIGHT_NEQ_WC__
(C++11)
|
expands to 1 if wide character encoding of the basic character set may not equal their narrow encoding (macro constant) |
__STDCPP_STRICT_POINTER_SAFETY__
(C++11)
|
expands to 1 if the implementation has strict std::pointer_safety (macro constant) |
__STDCPP_THREADS__
(C++11)
|
expands to 1 if the program can have more than one thread of execution (macro constant) |
The value 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.
[edit] 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(kkk, 23); #undef FUNCTION #define FUNCTION 34 #define OUTPUT(a) std::cout << #a << '\n' int main() { std::cout << "abcd: " << fun_abcd() << '\n'; std::cout << "fff: " << fun_fff() << '\n'; std::cout << "kkk: " << fun_kkk() << '\n'; std::cout << FUNCTION << '\n'; OUTPUT(million); //note the lack of quotes }
Output:
abcd: 12 fff: 2 kkk: 23 34 million