Namespaces
Variants
Views
Actions

Replacing text macros

From cppreference.com
 
 
C++ language
General topics
Preprocessor
Comments
Keywords
ASCII chart
Escape sequences
History of C++
Flow control
Conditional execution statements
Iteration statements
Jump statements
Functions
function declaration
lambda function declaration
function template
inline specifier
exception specifications (deprecated)
noexcept specifier (C++11)
Exceptions
Namespaces
Types
decltype specifier (C++11)
Specifiers
cv specifiers
storage duration specifiers
constexpr specifier (C++11)
auto specifier (C++11)
alignas specifier (C++11)
Literals
Expressions
alternative representations
Utilities
Types
typedef declaration
type alias declaration (C++11)
attributes (C++11)
Casts
implicit conversions
const_cast conversion
static_cast conversion
dynamic_cast conversion
reinterpret_cast conversion
C-style and functional cast
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
class template
function template
template specialization
parameter packs (C++11)
Miscellaneous
Inline assembly
 
 

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

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 backslahes 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.

A ## operator between any two successive identifiers in the replacement-list runs parameter replacement on the two identifiers 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.

[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 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.

[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