[cpp.subst] # 15 Preprocessing directives [[cpp]](./#cpp) ## 15.7 Macro replacement [[cpp.replace]](cpp.replace#cpp.subst) ### 15.7.2 Argument substitution [cpp.subst] [va-opt-replacement:](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") __VA_OPT__ ( [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")opt ) [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1670) After the arguments for the invocation of a function-like macro have been identified, argument substitution takes place[.](#1.sentence-1) For each parameter in the replacement list that is neither preceded by a # or ## preprocessing token nor followed by a ## preprocessing token, the preprocessing tokens naming the parameter are replaced by a preprocessing token sequence determined as follows: - [(1.1)](#1.1) If the parameter is of the form [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]"), the replacement preprocessing tokens are the preprocessing token sequence for the corresponding argument, as specified below[.](#1.1.sentence-1) - [(1.2)](#1.2) Otherwise, the replacement preprocessing tokens are the preprocessing tokens of corresponding argument after all macros contained therein have been expanded[.](#1.2.sentence-1) The argument's preprocessing tokens are completely macro replaced before being substituted as if they formed the rest of the preprocessing translation unit with no other preprocessing tokens being available[.](#1.2.sentence-2) [*Example [1](#example-1)*: #define LPAREN() (#define G(Q) 42#define F(R, X, ...) __VA_OPT__(G R X) )int x = F(LPAREN(), 0, <:-); // replaced by int x = 42; — *end example*] [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1700) An identifier __VA_ARGS__ that occurs in the replacement list shall be treated as if it were a parameter, and the variable arguments shall form the preprocessing tokens used to replace it[.](#2.sentence-1) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1706) [*Example [2](#example-2)*: #define debug(...) fprintf(stderr, __VA_ARGS__)#define showlist(...) puts(#__VA_ARGS__)#define report(test, ...) ((test) ? puts(#test) : printf(__VA_ARGS__)) debug("Flag"); debug("X = %d\n", x); showlist(The first, second, and third items.); report(x>y, "x is %d but y is %d", x, y); results infprintf(stderr, "Flag"); fprintf(stderr, "X = %d\n", x); puts("The first, second, and third items.");((x>y) ? puts("x>y") : printf("x is %d but y is %d", x, y)); — *end example*] [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/preprocessor.tex#L1726) The identifier __VA_OPT__ shall always occur as part of the preprocessing token sequence[*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]"); its closing ) is determined by skipping intervening pairs of matching left and right parentheses in its [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]")[.](#4.sentence-1) The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") of a [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") shall not contain __VA_OPT__[.](#4.sentence-2) If the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") would be ill-formed as the replacement list of the current function-like macro, the program is ill-formed[.](#4.sentence-3) A [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2 Argument substitution [cpp.subst]") is treated as if it were a parameter, and the preprocessing token sequence for the corresponding argument is defined as follows[.](#4.sentence-4) If the substitution of __VA_ARGS__ as neither an operand of # nor ## consists of no preprocessing tokens, the argument consists of a single placemarker preprocessing token ([[cpp.concat]](cpp.concat "15.7.4 The ## operator"), [[cpp.rescan]](cpp.rescan "15.7.5 Rescanning and further replacement"))[.](#4.sentence-5) Otherwise, the argument consists of the results of the expansion of the contained [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1 Preamble [cpp.pre]") as the replacement list of the current function-like macro before removal of placemarker tokens, rescanning, and further replacement[.](#4.sentence-6) [*Note [1](#note-1)*: The placemarker tokens are removed before stringization ([[cpp.stringize]](cpp.stringize "15.7.3 The # operator")), and can be removed by rescanning and further replacement ([[cpp.rescan]](cpp.rescan "15.7.5 Rescanning and further replacement"))[.](#4.sentence-7) — *end note*] [*Example [3](#example-3)*: #define F(...) f(0 __VA_OPT__(,) __VA_ARGS__)#define G(X, ...) f(0, X __VA_OPT__(,) __VA_ARGS__)#define SDEF(sname, ...) S sname __VA_OPT__(= { __VA_ARGS__ })#define EMP F(a, b, c) // replaced by f(0, a, b, c) F() // replaced by f(0) F(EMP) // replaced by f(0) 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) SDEF(foo); // replaced by S foo; SDEF(bar, 1, 2); // replaced by S bar = { 1, 2 };#define H1(X, ...) X __VA_OPT__(##) __VA_ARGS__ // error: ## may not appear at// the beginning of a replacement list ([[cpp.concat]](cpp.concat "15.7.4 The ## operator"))#define H2(X, Y, ...) __VA_OPT__(X ## Y,) __VA_ARGS__ H2(a, b, c, d) // replaced by ab, c, d#define H3(X, ...) #__VA_OPT__(X##X X##X) H3(, 0) // replaced by ""#define H4(X, ...) __VA_OPT__(a X ## X) ## b H4(, 1) // replaced by a b#define H5A(...) __VA_OPT__()/**/__VA_OPT__()#define H5B(X) a ## X ## b#define H5C(X) H5B(X) H5C(H5A()) // replaced by ab — *end example*]