There is a well-known problem that a macro like
#define foo(x, ...) something(whatever, __VA_ARGS__)
cannot work when the trailing argument list is empty because
you get the expansion something(whatever, )
GNU C provides ##__VA_ARGS__ which behaves like __VA_ARGS__ in
the nonempty case, and eats the prior comma in the empty case.
C++20 provides __VA_OPT__ which is used like __VA_OPT__(,) to
conditionally eat the comma. (GNU C has this also).
The question is: why wouldn't you just fix the semantics of __VA_ARG__
so that this is not necessary?
When would you ever want to interpolate __VA_ARGS__ into a replacement sequence such that if it is empty, and placed after a comma, that
comma does not disappear?
Kaz Kylheku <480-992-1380@kylheku.com> writes:
There is a well-known problem that a macro like
#define foo(x, ...) something(whatever, __VA_ARGS__)
cannot work when the trailing argument list is empty because
you get the expansion something(whatever, )
GNU C provides ##__VA_ARGS__ which behaves like __VA_ARGS__ in
the nonempty case, and eats the prior comma in the empty case.
C++20 provides __VA_OPT__ which is used like __VA_OPT__(,) to
conditionally eat the comma. (GNU C has this also).
The question is: why wouldn't you just fix the semantics of __VA_ARG__
so that this is not necessary?
When would you ever want to interpolate __VA_ARGS__ into a replacement
sequence such that if it is empty, and placed after a comma, that
comma does not disappear?
You might not want it (as a design feature), but there is probably code
out there that now depends on it.
On 2022-04-14, Ben <ben.usenet@bsb.me.uk> wrote:
Kaz Kylheku <480-992-1380@kylheku.com> writes:
There is a well-known problem that a macro like
#define foo(x, ...) something(whatever, __VA_ARGS__)
cannot work when the trailing argument list is empty because
you get the expansion something(whatever, )
GNU C provides ##__VA_ARGS__ which behaves like __VA_ARGS__ in
the nonempty case, and eats the prior comma in the empty case.
C++20 provides __VA_OPT__ which is used like __VA_OPT__(,) to
conditionally eat the comma. (GNU C has this also).
The question is: why wouldn't you just fix the semantics of __VA_ARG__
so that this is not necessary?
When would you ever want to interpolate __VA_ARGS__ into a replacement
sequence such that if it is empty, and placed after a comma, that
comma does not disappear?
You might not want it (as a design feature), but there is probably code
out there that now depends on it.
That's my question: what is the form of this dependency? What is an
example of something that breaks if __VA_ARGS__ eats the prior comma
when it has an empty expansion?
Of course, we can write regression test cases which verify that
the comma is not eaten, and I can think of ways of doing that:
#define mac(...) foo(, __VA_ARGS__)
#define xstr(x) str(x)
#define str(x) #x
assert (strcmp(xstr(mac()), "foo(, )") == 0);
printf("%s\n", xstr(mac()));
I mean, some way of relying on the comma that is actually useful.
There is a well-known problem that a macro like
#define foo(x, ...) something(whatever, __VA_ARGS__)
cannot work when the trailing argument list is empty because
you get the expansion something(whatever, )
GNU C provides ##__VA_ARGS__ which behaves like __VA_ARGS__ in
the nonempty case, and eats the prior comma in the empty case.
C++20 provides __VA_OPT__ which is used like __VA_OPT__(,) to
conditionally eat the comma. (GNU C has this also).
The question is: why wouldn't you just fix the semantics of
__VA_ARG__ so that this is not necessary?
Kaz Kylheku <480-992-1380@kylheku.com> writes:
There is a well-known problem that a macro like
#define foo(x, ...) something(whatever, __VA_ARGS__)
cannot work when the trailing argument list is empty because
you get the expansion something(whatever, )
GNU C provides ##__VA_ARGS__ which behaves like __VA_ARGS__ in
the nonempty case, and eats the prior comma in the empty case.
C++20 provides __VA_OPT__ which is used like __VA_OPT__(,) to
conditionally eat the comma. (GNU C has this also).
The question is: why wouldn't you just fix the semantics of
__VA_ARG__ so that this is not necessary?
This idea is considered in section "Alternative Designs" of
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2160.htm
On 2022-04-19, Tim Rentsch <tr.17687@z991.linuxsc.com> wrote:
Kaz Kylheku <480-992-1380@kylheku.com> writes:
There is a well-known problem that a macro like
#define foo(x, ...) something(whatever, __VA_ARGS__)
cannot work when the trailing argument list is empty because
you get the expansion something(whatever, )
GNU C provides ##__VA_ARGS__ which behaves like __VA_ARGS__ in
the nonempty case, and eats the prior comma in the empty case.
C++20 provides __VA_OPT__ which is used like __VA_OPT__(,) to
conditionally eat the comma. (GNU C has this also).
The question is: why wouldn't you just fix the semantics of
__VA_ARG__ so that this is not necessary?
This idea is considered in section "Alternative Designs" of
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2160.htm
Fantastic; thanks for that link!
The crux is that, for whatever reason, a macro like:
#define ADD_COMMA(...) , __VA_ARGS__
is tabled as an important requirement, and for that reason, F()
expanding to f(10), though identified as desirable, is not
considered; the automatic comma eating would break ADD_COMMA.
But! I think that could be acceptably handled like this:
#define FENCE
#define ADD_COMMA(...) , FENCE __VA_ARGS__
The rule that __VA_ARGS__ consumes the comma would be carried out
prior to the macro replacement of the token replacement sequence,
during which time FENCE is still there. Since FENCE doesn't look
like a comma, all is cool.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 366 |
Nodes: | 16 (2 / 14) |
Uptime: | 10:05:45 |
Calls: | 7,812 |
Files: | 12,924 |
Messages: | 5,765,526 |