Согласно N3092 (окончательный проект комитета С++ 11), в 16.3: Замена макроса, объектоподобный макрос определяется как:
# define identifier replacement-list new-line
и подобный функции макрос определяется как:
# 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
У всех есть список замены (так называемое значение макроса), и это определяется как:
replacement-list: pp-tokensopt
и pp-токены определяются как:
pp-tokens: preprocessing-token pp-tokens preprocessing-token
и токен предварительной обработки является, например, идентификатором.
Насколько я прочитал, макрос с пустым значением четко определен.
Тем не менее, 16.3-3 говорит:
Между идентификатором и списком замещения в определении объектоподобного макроса должен быть пробел.
и обратите внимание, что список замен сам по себе не является обязательным (хотя он может иметь пустое значение).
Поэтому я верю:
//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>
и, таким образом, например, так называемая "защита включения" должна иметь вид:
#ifndef is_xyz_included<NEWLINE>
#define is_xyz_included <NEWLINE> // NOTE THE SPACE BEFORE <NEWLINE>
#endif<NEWLINE>
Моя интерпретация неверна?