Are empty macro arguments legal in C++11? - c++

I sometimes deliberately omit macro arguments. For example, for a function-like macro like
#define MY_MACRO(A, B, C) ...
I might call it as:
MY_MACRO(, bar, baz)
There are still technically 3 arguments; it's just that the first one is "empty". This question is not about variadic macros.
When I do this I get warnings from g++ when compiling with -ansi (aka -std=c++98), but not when I use -std=c++0x. Does this mean that empty macro args are legal in the new C++ standard?
That's the entirety of my question, but anticipating the "why would you want to?" response, here's an example. I like keeping .h files uncluttered by function bodies, but implementing simple accessors outside of the .h file is tedious. I therefore wrote the following macro:
#define IMPLEMENT_ACCESSORS(TEMPLATE_DECL, RETURN_TYPE, CLASS, FUNCTION, MEMBER) \
TEMPLATE_DECL \
inline RETURN_TYPE* CLASS::Mutable##FUNCTION() { \
return &MEMBER; \
} \
\
TEMPLATE_DECL \
inline const RETURN_TYPE& CLASS::FUNCTION() const { \
return MEMBER; \
}
This is how I would use it for a class template that contains an int called int_:
IMPLEMENT_ACCESSORS(template<typename T>, int, MyTemplate<T>, Int, int_)
For a non-template class, I don't need template<typename T>, so I omit that macro argument:
IMPLEMENT_ACCESORS(, int, MyClass, Int, int_)

If I understand correctly, empty macro argument is allowed since C99 and
C++0x(11).
C99 6.10.3/4 says:
... the number of arguments (including those arguments consisting of
no preprocessing tokens) shall equal the number of parameters ...
and C++ N3290 16.3/4 has the same statement, while C++03 16.3/10 mentions:
... any argument consists of no preprocessing tokens, the behavior is
undefined.
I think empty argument comes under the representation arguments consisting of
no preprocessing tokens above.
Also, 6.10.3 in Rationale for International Standard Programming Languages C rev. 5.10
says:
A new feature of C99: Function-like macro invocations may also now
have empty arguments, that is, an argument may consist of no
preprocessing tokens.

Yes. The relevant bit is 16.3/11
The sequence of preprocessing tokens bounded by the outside-most
matching parentheses forms the list of arguments for the function-like
macro. The individual arguments within the list are separated by comma
preprocessing tokens.
There's no requirement that a single argument corresponds to precisely one token. In fact, the following section makes it clear that there can be more than one token per argument:
Before being substituted, each argument’s preprocessing tokens are
completely macro replaced as if they formed the rest of the
preprocessing file
In your case, one argument happens to correspond to zero tokens. That doesn't cause any contradiction.
[edit]
This was changed by N1566 to bring C++11 in line with C99.

When I do that I normally put a comment in place of the argument.
Place a macro that will be expanded to the empty string.
#define NOARG
...
MY_MACRO(/*Ignore this Param*/ NOARG, bar, baz)
PS. I got no warning with g++ with or without the -std=c++98 flag.
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
g++ (Apple Inc. build 5666) 4.2.1

Related

How to resolve "must specify at least one argument for '...' parameter of variadic macro"

You can define a variadic macro in C++ like:
#define FOO(x, ...) bar(x, __VA_ARGS__)
But calling FOO as FOO(1) results in the macro expansion bar(1,) which is obviously a syntactical error and won't compile.
Therefore GCC includes a GNU extension:
#define FOO(x, ...) bar(x, ##__VA_ARGS__)
which would expand the given example to the desired result bar(1). Although __VA_ARGS__ is a GNU extension it's support by clang too, but which emits a warning under the -pedantic flag:
warning: token pasting of ',' and __VA_ARGS__ is a GNU extension [-Wgnu-zero-variadic-macro-arguments].
Therefore C++20 includes a new mechanism to achieve the desired result in a standard compliant way:
#define FOO(x, ...) bar(x __VA_OPT__(,) __VA_ARGS__)
This will add the , only if the following __VA_ARGS__ are not empty, otherwise it will omit the ,. This new extension currently works with the GCC and clang trunks (with the -std=c++2a flag enabled): https://godbolt.org/z/k2nAE6.
My only problem is that clang emits a warning under -pedantic:
warning: must specify at least one argument for '...' parameter of variadic macro [-Wgnu-zero-variadic-macro-arguments] (GCC does not emit a warning).
But why? This only seems to make sense if someone only uses __VA_ARGS__ and passes no arguments to the macro. But with the new extension __VA_OPT__ I explicitly handle the case for which no argument is given.
So why would clang emit a warning in this case and how can I work around it?
This is already legal in C++20; it appears that Clang just hasn't updated their warnings yet.
The C++20 standard (from N4868) says in [cpp.replace.general]/5:
If the identifier-list in the macro definition does not end with an ellipsis [...] Otherwise, there shall be at least as many arguments in the invocation as there are parameters in the macro definition (excluding the ...). There shall exist a ) preprocessing token that terminates the invocation.
Compare with the bolded section with the equivalent statement in C++17's [cpp.replace]/4 (from N4659):
If the identifier-list in the macro definition does not end with an ellipsis [...] Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...). There shall exist a ) preprocessing token that terminates the invocation.
There is a similar comparison to be made between C++20's [cpp.replace.general]/15 and C++17's [cpp.replace]/12.
That is, C++17 had a requirement for FOO(x, ...) to be passed at least two arguments; C++20 has weakened that to only require one. Clang's -pedantic doesn't seem to have caught up yet.

Weird behavior of variadic macro expansion with gcc and clang

I'm writing a variadic dispatcher macro in C++, to call a different macro based on the number of arguments (from none up to 5) provided to the dispatcher. I came up with this solution:
#define GETOVERRIDE(_ignored, _1, _2, _3, _4, _5, NAME, ...) NAME
#define NAMEDARGS(...) GETOVERRIDE(ignored, ##__VA_ARGS__, NAMEDARGS5, NAMEDARGS4, NAMEDARGS3, NAMEDARGS2, NAMEDARGS1, NAMEDARGS0)(__VA_ARGS__)
NAMEDARGS is the dispatcher macro; calling it with 1 argument will result in a call to NAMEDARGS1 which takes 1 argument, and so on (I don't provide the implementations of the various NAMEDARGS# since they are irrelevant in this context).
I tested the code gcc 7.1.1, and I found a weird behavior of the gcc expansion when using the -std=c++14 flag. With this test code:
NAMEDARGS()
NAMEDARGS(int)
NAMEDARGS(int, float)
I get these expansions:
$ gcc -E testMacro.cpp
NAMEDARGS0()
NAMEDARGS1(int)
NAMEDARGS2(int, float)
$ gcc -E -std=c++14 testMacro.cpp
NAMEDARGS1()
NAMEDARGS1(int)
NAMEDARGS2(int, float)
It seems that using the -std=c++14 flag the substitution of the zero-argument call fails, resulting in the call of the one-argument macro. I thought that this could be because the ##__VA_ARGS__ syntax is a GNU extension, thus not working with an ISO C++ preprocessor; however, when trying with clang 4.0.1 I obtain the desired expansion:
$ clang -E -std=c++14 testMacro.cpp
NAMEDARGS0()
NAMEDARGS1(int)
NAMEDARGS2(int, float)
So I don't understand what's going on here. Does clang implement this gnu extension, accepting non-ISO code also with -std==c++14 unlike gcc? Or maybe the problem lies elsewhere? Thanks for the help.
GCC defaults -std to gnu++14 (see here), which is C++14 with GNU extensions.
Comparing the two with only NAMEDARGS(...) defined shows how the expansions differ:
Code
#define NAMEDARGS(...) GETOVERRIDE(ignored, ##__VA_ARGS__, NAMEDARGS5, NAMEDARGS4, NAMEDARGS3, NAMEDARGS2, NAMEDARGS1, NAMEDARGS0)(__VA_ARGS__)
NAMEDARGS()
-std=gnu++14 -E
GETOVERRIDE(ignored, NAMEDARGS5, NAMEDARGS4, NAMEDARGS3, NAMEDARGS2, NAMEDARGS1, NAMEDARGS0)()
-------------------^
-std=c++14 -E
GETOVERRIDE(ignored,, NAMEDARGS5, NAMEDARGS4, NAMEDARGS3, NAMEDARGS2, NAMEDARGS1, NAMEDARGS0)()
-------------------^^
I'm not an experienced standard reader, but I found the following two passages in [cpp.replace] which suggest that GCC is correct in both invocations:
If the identifier-list in the macro definition does not end with an ellipsis, the number of arguments (including those arguments consisting of no preprocessing tokens) in an invocation of a function-like macro shall equal the number of parameters in the macro definition. Otherwise, there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...). There shall exist a ) preprocessing token that terminates the invocation.
...
If there is a ... immediately preceding the ) in the function-like macro definition, then the trailing arguments, including any separating comma preprocessing tokens, are merged to form a single item: the variable arguments. The number of arguments so combined is such that, following merger, the number of arguments is one more than the number of parameters in the macro definition (excluding the ...).
It seems correct then that an empty __VA_ARGS__ is expanded to a single empty argument.
I can't find whether clang's behaviour here is intended.

Macro expansion order confusion between compilers

This piece of code compiles in Visual Studio 2015, but not in Clang:
#define COMMA ,
#define MC(a) a
#define MA(a,b,c) MC(a b c)
map <MA(int,COMMA,int)> FF;
It appears that Clang expands the COMMA macro before submitting it to the MC() macro. "Who is right" according to the C++ standard? Also, how can I make Clang behave like Visual Studio?
EDIT: Simplified the example, and changed some macro names.
Clang conforms to the standard; Visual Studio doesn't. I think you will have a lot of trouble getting Clang to not conform to the standard, so I won't attempt to answer "how do I get Clang to act like Visual Studio?". Maybe that wasn't really what you wanted to know.
When the compiler identifies the invocation of a function-like macro (that is, a macro with parameters) it expands the macro using the procedure explained in detail in §16.3 [cpp.replace] of the C++ standard. In the following, I've simplified the procedure by not considering the # and ## operators, because they do not appear in your example and the full procedure is more complicated.
We'll examine the invocation MC(int, COMMA, int). Here's what happens after the compiler sees the tokens MC and (, which indicate an invocation of the macro.
The compiler identifies what the arguments are, which involves finding the closing parenthesis. There are three arguments, which corresponds to the number of parameters, so that's OK. The arguments have not yet been expanded, so the compiler only sees the punctuation actually in the source file. It identifies the arguments as int, COMMA and int.
Every argument (except the ones whose corresponding parameter participates in token concatenation or stringification -- but, as I said, I'm not going to go into that scenario here) are then fully expanded. This happens before they are substituted into the macro body, so that the names of the macro's parameters don't leak out of the macro. So now the three arguments are int, , and int.
A copy of the macro body is made, in which each parameter is substituted with the corresponding (fully expanded) argument. The macro body ("replacement list", in standardese) was MC(A B C); after substituting the arguments, that becomes MC(A , C).
The sequence of tokens created in step 3 is inserted into the input in place of the macro invocation, and preprocessing continues.
At this point, the compiler will see the invocation of the function-like macro MC(A, B), and will proceed as above. However, this time the first step fails because two arguments are identified but the macro MC only has one parameter.

Argument Preceded by a # Token in a Macro

#define LINK_ENTITY_TO_CLASS(mapClassName,DLLClassName) \
static CEntityFactory<DLLClassName> mapClassName( #mapClassName );
This is a macro from the Alien Swarm mod for Half-Life 2, meant to be compiled with MSVC.
I've never seen an argument preceded by a # in a macro before, and I'm not sure if this is a MSVC specific thing or just uncommon. What does it mean?
This is part of both standard C and C++ and is not implementation-specific. The # preprocessing operator stringizes its argument. It takes whatever tokens were passed into the macro for the parameter designated by its operand (in this case, the parameter mapClassName) and makes a string literal out of them. So, for a simple example,
#define STRINGIZE(x) # x
STRINGIZE(Hello World)
// gets replaced with
"Hello World"
Note that the argument tokens are not macro replaced before they are stringized, so if Hello or World were defined as a macro, the result would still be the same. You need to use an extra level of indirection to get the arguments macro replaced (that linked answer discusses the concatenation operator, ##, but applies equally to the stringization operator.

What is the purpose of the ## operator in C++, and what is it called?

I was looking through the DXUTCore project that comes with the DirectX March 2009 SDK, and noticed that instead of making normal accessor methods, they used macros to create the generic accessors, similar to the following:
#define GET_ACCESSOR( x, y ) inline x Get##y() { DXUTLock l; return m_state.m_##y;};
...
GET_ACCESSOR( WCHAR*, WindowTitle );
It seems that the ## operator just inserts the text from the second argument into the macro to create a function operating on a variable using that text. Is this something that is standard in C++ (i.e. not Microsoft specific)? Is its use considered good practice? And, what is that operator called?
Token-pasting operator, used by the pre-processor to join two tokens into a single token.
This is also standard C++, contrary to what Raldolpho stated.
Here is the relevant information:
16.3.3 The ## operator [cpp.concat]
1 A ## preprocessing token shall not
occur at the beginning or at the end
of a replacement list for either form
of macro definition.
2 If, in the
replacement list, a parameter is
immediately preceded or followed by a
## preprocessing token, the parameter is replaced by the corresponding
argument’s preprocessing token
sequence.
3 For both object-like and
function-like macro invocations,
before the replacement list is
reexamined for more macro names to
replace, each instance of a ##
preprocessing token in the replacement
list (not from an argument) is deleted
and the preceding preprocessing token
is concatenated with the following
preprocessing token. If the result is
not a valid preprocessing token, the
behavior is undefined. The resulting
token is available for further macro
replacement. The order of evaluation
of ## operators is unspecified.
It's a preprocessing operator that concatenates left and right operands (without inserting whitespace). I don't think it's Microsoft specific.
This isn't Standard C++, it's Standard C. Check out this Wikipedia article.
And is it a good practice? In general, I hate pre-processor macros and think they're as bad as (if not worse than) Goto.
Edit: Apparently I'm being misunderstood by what I meant by "This isn't Standard C++, it's Standard C". Many people are reading the first phrase and failing to read the second. My intent is to point out that macros were inherited by C++ from C.
As Mehrdad said, it concatenates the operands, like:
#define MyMacro(A,B) A ## B
MyMacro(XYZ, 123) // Equivalent to XYZ123
Note that MISRA C suggests that this operand (and the # 'stringify' operand) should not be used due to the compiler dependent order of calculation.
It is token pasting operator allowed by Standard C++ (see 16.3.3 for details).
As for good practice: using macro is not a good practice IMHO (in C++).
it's the concatenation for macro arguments i.e.
GET_ACCESSOR (int, Age);
will be expended to
inline int GetAge() { DXUTLock l; return m_state.m_Age;};