Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c > #6430 > unrolled thread

Why doesn't __VA_LIST__ just eat the prior comma?

Started byKaz Kylheku <480-992-1380@kylheku.com>
First post2022-04-14 00:01 +0000
Last post2022-05-14 10:35 -0700
Articles 7 — 3 participants

Back to article view | Back to comp.std.c


Contents

  Why doesn't __VA_LIST__ just eat the prior comma? Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-14 00:01 +0000
    Re: Why doesn't __VA_LIST__ just eat the prior comma? Ben <ben.usenet@bsb.me.uk> - 2022-04-14 14:17 +0100
      Re: Why doesn't __VA_LIST__ just eat the prior comma? Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-18 16:59 +0000
        Re: Why doesn't __VA_LIST__ just eat the prior comma? Ben <ben.usenet@bsb.me.uk> - 2022-04-18 20:43 +0100
    Re: Why doesn't __VA_LIST__ just eat the prior comma? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-04-19 02:04 -0700
      Re: Why doesn't __VA_LIST__ just eat the prior comma? Kaz Kylheku <480-992-1380@kylheku.com> - 2022-04-20 02:02 +0000
        Re: Why doesn't __VA_LIST__ just eat the prior comma? Tim Rentsch <tr.17687@z991.linuxsc.com> - 2022-05-14 10:35 -0700

#6430 — Why doesn't __VA_LIST__ just eat the prior comma?

FromKaz Kylheku <480-992-1380@kylheku.com>
Date2022-04-14 00:01 +0000
SubjectWhy doesn't __VA_LIST__ just eat the prior comma?
Message-ID<20220413165157.844@kylheku.com>
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?

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

[toc] | [next] | [standalone]


#6431

FromBen <ben.usenet@bsb.me.uk>
Date2022-04-14 14:17 +0100
Message-ID<87czhju7ml.fsf@bsb.me.uk>
In reply to#6430
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.  The C committee is very reluctant to
break existing code, especially where the fix is more complex than
"search for 'restrict' to check it's not used".

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#6432

FromKaz Kylheku <480-992-1380@kylheku.com>
Date2022-04-18 16:59 +0000
Message-ID<20220418093916.295@kylheku.com>
In reply to#6431
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.

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.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal

[toc] | [prev] | [next] | [standalone]


#6433

FromBen <ben.usenet@bsb.me.uk>
Date2022-04-18 20:43 +0100
Message-ID<87bkwygotu.fsf@bsb.me.uk>
In reply to#6432
Kaz Kylheku <480-992-1380@kylheku.com> writes:

> 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?

I don't know of an example.

> 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.

The code does not have to find it actually useful for it to break on a
change.  If someone, somewhere, ended up having to work around this
issue, that code will break even if the programmer might now be glad of
the opportunity to simplify it.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#6434

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-04-19 02:04 -0700
Message-ID<861qxta1gb.fsf@linuxsc.com>
In reply to#6430
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

[toc] | [prev] | [next] | [standalone]


#6435

FromKaz Kylheku <480-992-1380@kylheku.com>
Date2022-04-20 02:02 +0000
Message-ID<20220419183244.563@kylheku.com>
In reply to#6434
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.

(This seems natural because the substitution of __VA_ARGS__ should in fact
be taking place during argument replacement, and not during the
rescanning of the argument-substituted replacement sequence for more
macros.)

[toc] | [prev] | [next] | [standalone]


#6437

FromTim Rentsch <tr.17687@z991.linuxsc.com>
Date2022-05-14 10:35 -0700
Message-ID<86a6bk3tm7.fsf@linuxsc.com>
In reply to#6435
Kaz Kylheku <480-992-1380@kylheku.com> writes:

> 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.

If you feel strongly about it, write up a proposal and submit it
to the two committees.  Given that __VA_OPT__ has already been
adopted in C++20, any alternate scheme faces an uphill climb, and
so if no one feels strongly enough to try to get some other
scheme through the standardization process then it seems rather
pointless to discuss it.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.std.c


csiph-web