On 2022-04-14, Ben <
ben.u...@bsb.me.uk> wrote:
> Kaz Kylheku <
480-99...@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.
If I wanted to stringify mac() for some useful purpose in some real
program, I would actually prefer the result "foo( )" or "foo()".
I'd likely need a post-processing run-time pass to convert "(, )"
occurrences to "()". I'd probably have some conditionals to do it
in the preprocessor, so that the post-processing code can be
compiled out.