Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 nested macro invocation?

Tags:

c++

c

c++11

macros

It says in C++ std 16.3.4:

The resulting preprocessing token sequence [from a macro invocation replacement] is rescanned, along with all subsequent preprocessing tokens of the source file, for more macro names to replace.

If the name of the macro being replaced is found during this scan of the replacement list (not including the rest of the source file’s preprocessing tokens), it is not replaced.

Furthermore, if any nested replacements encounter the name of the macro being replaced, it is not replaced.

These nonreplaced macro name preprocessing tokens are no longer available for further replacement even if they are later (re)examined in contexts in which that macro name preprocessing token would otherwise have been replaced.

What exactly is a nested macro replacement?

Specifically consider:

#define f(x) 1 x
#define g(x) 2 x

g(f)(g)(3)

I would have expected the following:

g(f)(g)(3)    <-- first replacement of g, ok
2 f(g)(3)     <-- nested replacement of f, ok
2 1 g(3)      <-- second nested replacement of g, don't replace, stop

However gcc unexpectedly goes ahead with the second replacement of g, producing:

2 1 2 3

Any ideas?

Update:

After much research, let me clear up this issue with a simpler example:

#define A(x) B
#define B(x) A(x)

A(i)(j)

This expands as follows:

A(i)(j)
B(j)
A(j)

The standard does not specify whether A(j) should be expanded to B or not. The committee decided to leave it this way because real world programs are not expected to depend on this behavior, so both leaving A(j) unexpanded and expanding A(j) to B are considered conformant.

like image 835
Andrew Tomazos Avatar asked Mar 23 '13 03:03

Andrew Tomazos


People also ask

What are nested macro calls?

A nested macro instruction definition is a macro instruction definition you can specify as a set of model statements in the body of an enclosing macro definition. This lets you create a macro definition by expanding the outer macro that contains the nested definition.

Are nested macros allowed in C?

The C preprocessor and macros are one of the most useful elements for writing portable C/C++ code . It even can be used to completely different purposes, like text processing. However, it suffers one major drawback: it does not support nested macros expansion (put differently, macros within macros).

Are nested macros allowed?

Nested macros are allowed.

What is ## in macro in C?

This is called token pasting or token concatenation. The '##' pre-processing operator performs token pasting. When a macro is expanded, the two tokens on either side of each '##' operator are combined into a single token, which then replaces the '##' and the two original tokens in the macro expansion.


1 Answers

This explains the original intent, and why no clarifications have been added to the standard about this subject:

http://open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#268


268. Macro name suppression in rescanned replacement text

Section: 16.3.4 [cpp.rescan]     Status: open     Submitter: Bjarne Stroustrup     Date: 18 Jan 2001

It is not clear from the Standard what the result of the following example should be:

#define NIL(xxx) xxx
#define G_0(arg) NIL(G_1)(arg)
#define G_1(arg) NIL(arg)
G_0(42)

The relevant text from the Standard is found in 16.3.4 [cpp.rescan] paragraph 2:

[snipped]

The sequence of expansion of G0(42) is as follows:

G0(42)
NIL(G_1)(42)
G_1(42)
NIL(42)

The question is whether the use of NIL in the last line of this sequence qualifies for non-replacement under the cited text. If it does, the result will be NIL(42). If it does not, the result will be simply 42.

The original intent of the J11 committee in this text was that the result should be 42, as demonstrated by the original pseudo-code description of the replacement algorithm provided by Dave Prosser, its author. The English description, however, omits some of the subtleties of the pseudo-code and thus arguably gives an incorrect answer for this case.

Suggested resolution (Mike Miller): [snipped]

Notes (via Tom Plum) from April, 2004 WG14 Meeting:

Back in the 1980's it was understood by several WG14 people that there were tiny differences between the "non-replacement" verbiage and the attempts to produce pseudo-code. The committee's decision was that no realistic programs "in the wild" would venture into this area, and trying to reduce the uncertainties is not worth the risk of changing conformance status of implementations or programs.

like image 67
Mara Bos Avatar answered Oct 22 '22 07:10

Mara Bos