Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are empty macros allowed by the C++ language standard?

According to N3092 (final committee draft of C++11), in 16.3: Macro replacement, object-like macro is defined as:

# define identifier replacement-list new-line

and function-like macro is defined as:

# define identifier lparen identifier-list_opt ) replacement-list new-line
# define identifier lparen ... ) replacement-list new-line
# define identifier lparen identifier-list , ... ) replacement-list new-line

All have replacement-list (so-called macro value) and this is defined as:

replacement-list:
     pp-tokensopt

and pp-tokens is defined as:

pp-tokens:
    preprocessing-token
    pp-tokens preprocessing-token

and preprocessing-token is, for example, identifier.

As far as I read these, a macro with an empty value is well-defined.
However, 16.3-3 says:

There shall be white-space between the identifier and the replacement list in the definition of an object-like macro.

and note that replacement-list itself is not optional (though it can have an empty value).

So I believe:

//well-formed (function-like macro with value)
#define f(x) (x)<NEWLINE>

//well-formed (function-like macro without value)
#define f(x)<NEWLINE>

//well-formed (function-like macro without value)
#define f(x) <NEWLINE>

//well-formed (object-like macro with value)
#define f hello<NEWLINE>

//**ill-formed** (object-like macro without value)
#define f<NEWLINE>

//well-formed (object-like macro without value)
#define f <NEWLINE>

and thus, for example, a so-called "include guard" should be of the form:

#ifndef is_xyz_included<NEWLINE>
    #define is_xyz_included <NEWLINE> // NOTE THE SPACE BEFORE <NEWLINE>
#endif<NEWLINE>

Is my interpretation wrong?

like image 994
ynn Avatar asked May 23 '19 04:05

ynn


1 Answers

I believe your interpretation is correct. A valid include guard must therefore be of the form you describe, with a white-space that is not a newline. Not a newline because of

[cpp]

4 The only white-space characters that shall appear between preprocessing tokens within a preprocessing directive (from just after the introducing # preprocessing token through just before the terminating new-line character) are space and horizontal-tab (including spaces that have replaced comments or possibly other white-space characters in translation phase 3).

which precludes a new-line from being the white-space talked about in the paragraph you mentioned.

But given how common this idiom is with include guards, so much so that the standard itself contains such an example, this is probably a wording defect that is based on the assumption that a replacement list must not be empty for the macro to be of any use.

It's worth mentioning that it's a wording defect shared with the C standard, as far as my survey of the wording found.

like image 66
StoryTeller - Unslander Monica Avatar answered Oct 14 '22 11:10

StoryTeller - Unslander Monica