This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

105
cppdraft/cpp/subst.md Normal file
View File

@@ -0,0 +1,105 @@
[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.2Argument substitution[cpp.subst]")
__VA_OPT__ ( [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1Preamble[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.2Argument 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.2Argument 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.1Preamble[cpp.pre]")[.](#4.sentence-1)
The [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1Preamble[cpp.pre]") of a [*va-opt-replacement*](#nt:va-opt-replacement "15.7.2Argument substitution[cpp.subst]") shall not contain __VA_OPT__[.](#4.sentence-2)
If the [*pp-tokens*](cpp.pre#nt:pp-tokens "15.1Preamble[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.2Argument 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.4The ## operator"), [[cpp.rescan]](cpp.rescan "15.7.5Rescanning 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.1Preamble[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.3The # operator")),
and can be removed by rescanning and further replacement ([[cpp.rescan]](cpp.rescan "15.7.5Rescanning 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.4The ## 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*]