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


Groups > comp.lang.c++ > #122015 > unrolled thread

({

Started byAlan Mackenzie <acm@muc.de>
First post2025-03-20 18:27 +0000
Last post2025-04-01 06:59 +0200
Articles 15 — 7 participants

Back to article view | Back to comp.lang.c++


Contents

  ({ Alan Mackenzie <acm@muc.de> - 2025-03-20 18:27 +0000
    Re: ({ Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-21 09:58 +0100
      Re: ({ Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-22 16:14 +0100
    Re: ({ Paavo Helde <eesnimi@osa.pri.ee> - 2025-03-21 12:54 +0200
      Re: ({ Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2025-03-21 12:27 -0700
        Re: ({ Bonita Montero <Bonita.Montero@gmail.com> - 2025-03-22 10:09 +0100
          Re: ({ Alan Mackenzie <acm@muc.de> - 2025-03-22 11:26 +0000
        Re: ({ Alan Mackenzie <acm@muc.de> - 2025-03-22 11:00 +0000
      Re: ({ Alan Mackenzie <acm@muc.de> - 2025-03-22 10:53 +0000
        Re: ({ scott@slp53.sl.home (Scott Lurndal) - 2025-03-22 14:09 +0000
          Re: ({ Alan Mackenzie <acm@muc.de> - 2025-03-22 15:20 +0000
            Re: ({ scott@slp53.sl.home (Scott Lurndal) - 2025-03-22 15:53 +0000
        Re: ({ Paavo Helde <eesnimi@osa.pri.ee> - 2025-03-22 17:18 +0200
          Re: ({ David Brown <david.brown@hesbynett.no> - 2025-03-22 17:45 +0100
      Re: ({ Jakob Bohm <egenagwemdimtapsar@jbohm.dk> - 2025-04-01 06:59 +0200

#122015 — ({

FromAlan Mackenzie <acm@muc.de>
Date2025-03-20 18:27 +0000
Subject({
Message-ID<vrhmme$8v0$1@news.muc.de>
Hello, C++.

I'm having some difficulty (amending Emacs's C++ Mode) reconciling the
two conflicting uses in C++ of ({.

Firstly, it is used as a "statement expression", a GCC enhancement also
found in C, allowing a more relaxed and natural way to write an
expression as the end result of a sequence of statements:

     ({ int y = foo (); int z;
        if (y > 0) z = y;
	else z = - y;
	z; })

.  I think this usage is very old.

Secondly, there's initialisation expressions like:

  void f4 (int a, int b, int c)
  {
    std::vector<ABC> abcList2(
      {{a+6,
        b+6,
        c+6}
      }
      );
  ....
  }

.  Here the ( on the std::vector line, together with the next {, can be
confused as a statement expression, though it's clearly not meant that
way.  I think this syntax is much newer than the other one, though I may
be wrong here.

In calculating the indentation for source lines in these constructs, the
ambiguity causes mis-indentation for one or the other of them.

Now to my question: how common is GCC's statement expression in the wide
world of C++ source code?  How much would be lost if I simply removed the
statement expression from C++ Mode's parsing functions?

-- 
Alan Mackenzie (Nuremberg, Germany).

[toc] | [next] | [standalone]


#122016

FromBonita Montero <Bonita.Montero@gmail.com>
Date2025-03-21 09:58 +0100
Message-ID<vrj9o2$176cr$1@raubtier-asyl.eternal-september.org>
In reply to#122015
Am 20.03.2025 um 19:27 schrieb Alan Mackenzie:
> Hello, C++.
> 
> I'm having some difficulty (amending Emacs's C++ Mode) reconciling the
> two conflicting uses in C++ of ({.
> 
> Firstly, it is used as a "statement expression", a GCC enhancement also
> found in C, allowing a more relaxed and natural way to write an
> expression as the end result of a sequence of statements:
> 
>       ({ int y = foo (); int z;
>          if (y > 0) z = y;
> 	else z = - y;
> 	z; })

If the sign of y is badly predictible you may chose:

z = (y >> sizeof(y) * CHAR_BIT - 1) * y;


> .  I think this usage is very old.
> 
> Secondly, there's initialisation expressions like:
> 
>    void f4 (int a, int b, int c)
>    {
>      std::vector<ABC> abcList2(
>        {{a+6,
>          b+6,
>          c+6}
>        }
>        );
>    ....
>    }
> 
> .  Here the ( on the std::vector line, together with the next {, can be
> confused as a statement expression, though it's clearly not meant that
> way.  I think this syntax is much newer than the other one, though I may
> be wrong here.
> 
> In calculating the indentation for source lines in these constructs, the
> ambiguity causes mis-indentation for one or the other of them.
> 
> Now to my question: how common is GCC's statement expression in the wide
> world of C++ source code?  How much would be lost if I simply removed the
> statement expression from C++ Mode's parsing functions?
> 

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


#122024

FromBonita Montero <Bonita.Montero@gmail.com>
Date2025-03-22 16:14 +0100
Message-ID<vrmk4n$7524$1@raubtier-asyl.eternal-september.org>
In reply to#122016
Am 21.03.2025 um 09:58 schrieb Bonita Montero:

>>       ({ int y = foo (); int z;
>>          if (y > 0) z = y;
>>     else z = - y;
>>     z; })

> If the sign of y is badly predictible you may chose:

> z = (y >> sizeof(y) * CHAR_BIT - 1) * y;

Sorry, your code is more efficient since it can be substituted by
a negate i a second register and a conditional move. But some archi-
tectures like RISC-V don't have conditional moves and my code would
be the most efficient way to handle this.

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


#122017

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2025-03-21 12:54 +0200
Message-ID<vrjgh8$1bqpn$1@dont-email.me>
In reply to#122015
On 20.03.2025 20:27, Alan Mackenzie wrote:
> Hello, C++.
> 
> I'm having some difficulty (amending Emacs's C++ Mode) reconciling the
> two conflicting uses in C++ of ({.
> 
> Firstly, it is used as a "statement expression", a GCC enhancement also
> found in C, allowing a more relaxed and natural way to write an
> expression as the end result of a sequence of statements:
> 
>       ({ int y = foo (); int z;
>          if (y > 0) z = y;
> 	else z = - y;
> 	z; })
> 
> .  I think this usage is very old.
> 
> Secondly, there's initialisation expressions like:
> 
>    void f4 (int a, int b, int c)
>    {
>      std::vector<ABC> abcList2(
>        {{a+6,
>          b+6,
>          c+6}
>        }
>        );
>    ....
>    }
> 
> .  Here the ( on the std::vector line, together with the next {, can be
> confused as a statement expression, though it's clearly not meant that
> way.  I think this syntax is much newer than the other one, though I may
> be wrong here.

This braced initialization (called "List-initialization") was introduced 
in C++11, it is standardized and in wide and growing use.

> 
> In calculating the indentation for source lines in these constructs, the
> ambiguity causes mis-indentation for one or the other of them.
> 
> Now to my question: how common is GCC's statement expression in the wide
> world of C++ source code?  How much would be lost if I simply removed the
> statement expression from C++ Mode's parsing functions?

It appears the statement expressions are a gcc extension which does not 
even compile in standard C++, and is probably not needed for anything in 
C++ as there are better options like templated and inlined functions.
In C there might be some usage case for it.

During the last 25 years I do not recall having encountered this feature 
ever, and I do not even recall anyone bashing it. So I guess it could be 
ditched pretty easily.


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


#122018

FromKeith Thompson <Keith.S.Thompson+u@gmail.com>
Date2025-03-21 12:27 -0700
Message-ID<87ldsyqj40.fsf@nosuchdomain.example.com>
In reply to#122017
Paavo Helde <eesnimi@osa.pri.ee> writes:
[...]
> It appears the statement expressions are a gcc extension which does
> not even compile in standard C++, and is probably not needed for
> anything in C++ as there are better options like templated and inlined
> functions.
> In C there might be some usage case for it.
[...]

Statement expressions don't compile in *standard* C or C++.

gcc supports them as an extension for both C and C++ (and Objective-C).

-- 
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
void Void(void) { Void(); } /* The recursive call of the void */

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


#122019

FromBonita Montero <Bonita.Montero@gmail.com>
Date2025-03-22 10:09 +0100
Message-ID<vrlunj$3kg23$1@raubtier-asyl.eternal-september.org>
In reply to#122018
Am 21.03.2025 um 20:27 schrieb Keith Thompson:

> Statement expressions don't compile in *standard* C or C++.

In C++ you could use lambdas for that.

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


#122022

FromAlan Mackenzie <acm@muc.de>
Date2025-03-22 11:26 +0000
Message-ID<vrm6p7$2ue$3@news.muc.de>
In reply to#122019
Bonita Montero <Bonita.Montero@gmail.com> wrote:
> Am 21.03.2025 um 20:27 schrieb Keith Thompson:

>> Statement expressions don't compile in *standard* C or C++.

> In C++ you could use lambdas for that.

The sort of thing statement expressions are good at are the likes of (C
example):

    while ({
             ch = getch ();
	     ch = toupper (ch);
	     ch != 'Q';
	   })
        switch (ch) {
	....
	}

, the loop of a command processing function which takes single case
insensitive commands from the keyboard.  While it is true that this
example could be rewritten using the comma operator in place of the
statement expression, it would only need to be slightly more complicated
to make this impractical.

Yes, in C++, a lambda could be used instead, but this is somewhat
artificial and would have more boilerplate cluttering up the actual code.

Anyhow, I haven't actually done any real C++ hacking for about 20 years,
I just try to keep Emacs's C++ Mode working.

-- 
Alan Mackenzie (Nuremberg, Germany).

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


#122021

FromAlan Mackenzie <acm@muc.de>
Date2025-03-22 11:00 +0000
Message-ID<vrm58i$2ue$2@news.muc.de>
In reply to#122018
Keith Thompson <Keith.S.Thompson+u@gmail.com> wrote:
> Paavo Helde <eesnimi@osa.pri.ee> writes:
> [...]
>> It appears the statement expressions are a gcc extension which does
>> not even compile in standard C++, and is probably not needed for
>> anything in C++ as there are better options like templated and inlined
>> functions.
>> In C there might be some usage case for it.
> [...]

> Statement expressions don't compile in *standard* C or C++.

More precisely, they're not standard C or C++.  I think it is a shame
they never became part of the standard, as no doubt their developers
intended.

> gcc supports them as an extension for both C and C++ (and Objective-C).

There are instances of statement expressions in the Linux kernel,
developed under GCC, and clang was enhanced to support them too so as to
be able to compile Linux.  Or so I've heard.

> -- 
> Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
> void Void(void) { Void(); } /* The recursive call of the void */

-- 
Alan Mackenzie (Nuremberg, Germany).

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


#122020

FromAlan Mackenzie <acm@muc.de>
Date2025-03-22 10:53 +0000
Message-ID<vrm4rl$2ue$1@news.muc.de>
In reply to#122017
Paavo Helde <eesnimi@osa.pri.ee> wrote:
> On 20.03.2025 20:27, Alan Mackenzie wrote:
>> Hello, C++.

>> I'm having some difficulty (amending Emacs's C++ Mode) reconciling the
>> two conflicting uses in C++ of ({.

>> Firstly, it is used as a "statement expression", a GCC enhancement also
>> found in C, allowing a more relaxed and natural way to write an
>> expression as the end result of a sequence of statements:

>>       ({ int y = foo (); int z;
>>          if (y > 0) z = y;
>>       else z = - y;
>>       z; })

>> .  I think this usage is very old.

>> Secondly, there's initialisation expressions like:

>>    void f4 (int a, int b, int c)
>>    {
>>      std::vector<ABC> abcList2(
>>        {{a+6,
>>          b+6,
>>          c+6}
>>        }
>>        );
>>    ....
>>    }

>> .  Here the ( on the std::vector line, together with the next {, can be
>> confused as a statement expression, though it's clearly not meant that
>> way.  I think this syntax is much newer than the other one, though I may
>> be wrong here.

> This braced initialization (called "List-initialization") was introduced 
> in C++11, it is standardized and in wide and growing use.

Yes, thanks.

>> In calculating the indentation for source lines in these constructs, the
>> ambiguity causes mis-indentation for one or the other of them.

>> Now to my question: how common is GCC's statement expression in the wide
>> world of C++ source code?  How much would be lost if I simply removed the
>> statement expression from C++ Mode's parsing functions?

> It appears the statement expressions are a gcc extension which does not 
> even compile in standard C++, and is probably not needed for anything in 
> C++ as there are better options like templated and inlined functions.
> In C there might be some usage case for it.

I'm not sure what you meant by templated functions here, but an inline
function has the disadvantage of fragmenting the code.  Rather than have
a few lines of code where they're used, you need to look somewhere else
to see what they do.

There are some uses of the statement expression in the (C) Linux kernel
sources.

> During the last 25 years I do not recall having encountered this feature 
> ever, and I do not even recall anyone bashing it. So I guess it could be 
> ditched pretty easily.

Thanks, that was what I thought.  But in the last couple of days, I might
have come up with a way to parse both of the ({ constructs without (too
much) ambiguity.

-- 
Alan Mackenzie (Nuremberg, Germany).

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


#122023

Fromscott@slp53.sl.home (Scott Lurndal)
Date2025-03-22 14:09 +0000
Message-ID<lwzDP.1208305$_N6e.415187@fx17.iad>
In reply to#122020
Alan Mackenzie <acm@muc.de> writes:
>Paavo Helde <eesnimi@osa.pri.ee> wrote:
>> On 20.03.2025 20:27, Alan Mackenzie wrote:

>> It appears the statement expressions are a gcc extension which does not 
>> even compile in standard C++, and is probably not needed for anything in 
>> C++ as there are better options like templated and inlined functions.
>> In C there might be some usage case for it.
>
>I'm not sure what you meant by templated functions here, but an inline
>function has the disadvantage of fragmenting the code.  Rather than have
>a few lines of code where they're used, you need to look somewhere else
>to see what they do.

An inline function name should be chosen such that it is sufficient to
define exactly what the effect of the function call will be, while
still hiding the implementation and improving readability.

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


#122026

FromAlan Mackenzie <acm@muc.de>
Date2025-03-22 15:20 +0000
Message-ID<vrmkg3$308h$2@news.muc.de>
In reply to#122023
Scott Lurndal <scott@slp53.sl.home> wrote:
> Alan Mackenzie <acm@muc.de> writes:
>>Paavo Helde <eesnimi@osa.pri.ee> wrote:
>>> On 20.03.2025 20:27, Alan Mackenzie wrote:

>>> It appears the statement expressions are a gcc extension which does not 
>>> even compile in standard C++, and is probably not needed for anything in 
>>> C++ as there are better options like templated and inlined functions.
>>> In C there might be some usage case for it.

>>I'm not sure what you meant by templated functions here, but an inline
>>function has the disadvantage of fragmenting the code.  Rather than have
>>a few lines of code where they're used, you need to look somewhere else
>>to see what they do.

> An inline function name should be chosen such that it is sufficient to
> define exactly what the effect of the function call will be, while
> still hiding the implementation and improving readability.

Yes, that's fine in theory.  In practice, meaning while debugging, a
whole lot of midget functions, each called something like
convert_next_char_to_upper_case_is_it_Q_p is a nightmare.  That name is
more difficult to understand than the three lines of code (see another
of my posts in this thread) it replaces.

While debugging, _nothing_ can be trusted to do what it says, and a
hidden implementation makes things worse - rather than having to scroll
a window to the inline function, it's probably in a different file.

Even a single midget function which isn't a coherent thing makes
debugging more irksome than simply having the three lines of code
physically in the larger function where they are actually used.

-- 
Alan Mackenzie (Nuremberg, Germany).

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


#122027

Fromscott@slp53.sl.home (Scott Lurndal)
Date2025-03-22 15:53 +0000
Message-ID<i2BDP.304568$SVG3.140032@fx42.iad>
In reply to#122026
Alan Mackenzie <acm@muc.de> writes:
>Scott Lurndal <scott@slp53.sl.home> wrote:
>> Alan Mackenzie <acm@muc.de> writes:
>>>Paavo Helde <eesnimi@osa.pri.ee> wrote:
>>>> On 20.03.2025 20:27, Alan Mackenzie wrote:
>
>>>> It appears the statement expressions are a gcc extension which does not 
>>>> even compile in standard C++, and is probably not needed for anything in 
>>>> C++ as there are better options like templated and inlined functions.
>>>> In C there might be some usage case for it.
>
>>>I'm not sure what you meant by templated functions here, but an inline
>>>function has the disadvantage of fragmenting the code.  Rather than have
>>>a few lines of code where they're used, you need to look somewhere else
>>>to see what they do.
>
>> An inline function name should be chosen such that it is sufficient to
>> define exactly what the effect of the function call will be, while
>> still hiding the implementation and improving readability.
>
>Yes, that's fine in theory.  In practice, meaning while debugging, a
>whole lot of midget functions, each called something like
>convert_next_char_to_upper_case_is_it_Q_p is a nightmare. 

Strawman.   Nobody suggested that a meaningful name
requires forty characters.

  inline bool is_ep(void) const { return flags & PCC_EP;} 

is perfectly cromulent.

Gdb() has no problem stepping through that, and shows the
corresponding source.

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


#122025

FromPaavo Helde <eesnimi@osa.pri.ee>
Date2025-03-22 17:18 +0200
Message-ID<vrmkd2$67va$1@dont-email.me>
In reply to#122020
On 22.03.2025 12:53, Alan Mackenzie wrote:
> Paavo Helde <eesnimi@osa.pri.ee> wrote:
>> It appears the statement expressions are a gcc extension which does not
>> even compile in standard C++, and is probably not needed for anything in
>> C++ as there are better options like templated and inlined functions.
>> In C there might be some usage case for it.
> 
> I'm not sure what you meant by templated functions here, but an inline
> function has the disadvantage of fragmenting the code.  Rather than have
> a few lines of code where they're used, you need to look somewhere else
> to see what they do.

At the GCC page for statement expressions they say "This feature is 
especially useful in making macro definitions “safe” (so that they 
evaluate each operand exactly once)" and most of their examples are 
about macros.

A macro is fragmenting the code exactly in the same way as an inline 
function, except the macros are worse than functions in multiple ways. 
In C one might argue macros are needed for supporting multiple types at 
the same time, but in C++ this is solved much better by function templates.

Ergo, a C-style macro using statement expressions can easily replaced 
with a more regular and better behaving function or function template in 
C++, with no increase in code "fragmentation".

For "in-place" use Bonita is right a lambda can be used to the same 
effect, but the readability probably does not go better. As per the 
first example on the GCC page (poor man implementation of abs()):

int a = ({ int y = foo (); int z; if (y > 0) z = y; else z = - y; z; });

can be written with a lambda in C++:

int a = [](){int y = foo (); int z; if (y > 0) z = y; else z = - y; 
return z; }();

I suspect Bonita might like this. I still prefer the more mundane

int a = std::abs(foo());

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


#122028

FromDavid Brown <david.brown@hesbynett.no>
Date2025-03-22 17:45 +0100
Message-ID<vrmpft$a537$1@dont-email.me>
In reply to#122025
On 22/03/2025 16:18, Paavo Helde wrote:
> On 22.03.2025 12:53, Alan Mackenzie wrote:
>> Paavo Helde <eesnimi@osa.pri.ee> wrote:
>>> It appears the statement expressions are a gcc extension which does not
>>> even compile in standard C++, and is probably not needed for anything in
>>> C++ as there are better options like templated and inlined functions.
>>> In C there might be some usage case for it.
>>
>> I'm not sure what you meant by templated functions here, but an inline
>> function has the disadvantage of fragmenting the code.  Rather than have
>> a few lines of code where they're used, you need to look somewhere else
>> to see what they do.
> 
> At the GCC page for statement expressions they say "This feature is 
> especially useful in making macro definitions “safe” (so that they 
> evaluate each operand exactly once)" and most of their examples are 
> about macros.
> 
> A macro is fragmenting the code exactly in the same way as an inline 
> function, except the macros are worse than functions in multiple ways. 
> In C one might argue macros are needed for supporting multiple types at 
> the same time, but in C++ this is solved much better by function templates.
> 
> Ergo, a C-style macro using statement expressions can easily replaced 
> with a more regular and better behaving function or function template in 
> C++, with no increase in code "fragmentation".
> 
> For "in-place" use Bonita is right a lambda can be used to the same 
> effect, but the readability probably does not go better. As per the 
> first example on the GCC page (poor man implementation of abs()):
> 
> int a = ({ int y = foo (); int z; if (y > 0) z = y; else z = - y; z; });
> 

It can also combine well with type inference, such as the example from 
GCC's reference:

#define max(a, b) \
	({ __auto_type _a = (a); __auto_type _b = (b); \
	  _a > _b ? _a : _b; })

(In C23, "auto" is approximately equivalent to "auto" in C++, so you 
don't need the gcc "__auto_type" extension any more.)

Of course such function-like macros are usually best replaced with 
template functions in C++.  I can't think off-hand of a situation where 
statement expressions in C++ would be significantly better than either 
an inline function / function template, or an immediately-invoked lambda.


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


#122096

FromJakob Bohm <egenagwemdimtapsar@jbohm.dk>
Date2025-04-01 06:59 +0200
Message-ID<vsfrqn$28p75$1@dont-email.me>
In reply to#122017
On 2025-03-21 11:54, Paavo Helde wrote:
> On 20.03.2025 20:27, Alan Mackenzie wrote:
>> Hello, C++.
>>
>> I'm having some difficulty (amending Emacs's C++ Mode) reconciling the
>> two conflicting uses in C++ of ({.
>>
>> Firstly, it is used as a "statement expression", a GCC enhancement also
>> found in C, allowing a more relaxed and natural way to write an
>> expression as the end result of a sequence of statements:
>>
>>       ({ int y = foo (); int z;
>>          if (y > 0) z = y;
>>     else z = - y;
>>     z; })
>>
>> .  I think this usage is very old.
>>
>> Secondly, there's initialisation expressions like:
>>
>>    void f4 (int a, int b, int c)
>>    {
>>      std::vector<ABC> abcList2(
>>        {{a+6,
>>          b+6,
>>          c+6}
>>        }
>>        );
>>    ....
>>    }
>>
>> .  Here the ( on the std::vector line, together with the next {, can be
>> confused as a statement expression, though it's clearly not meant that
>> way.  I think this syntax is much newer than the other one, though I may
>> be wrong here.
> 
> This braced initialization (called "List-initialization") was introduced 
> in C++11, it is standardized and in wide and growing use.
> 

Actually, it is from K&R C, except (perhaps) the option to put the list 
expression in a pair of regular parenthesis with the usual identical 
meaning.  The basic K&R form is:

int smallprimes[4] = { 2, 3, 5, 7 };
int identitymatrix[2][2] = { { 1, 0 }, { 0, 1 } };

In ANSI C, these can be declared const and placed in a read-only part of 
the resulting program file.  This was broken by the desire to allocate 
all data on the heap via heap-centric classes like vector<int> .


   Enjoy

   Jakob

-- 
Jakob Bohm, MSc.Eng., I speak only for myself, not my company
This public discussion message is non-binding and may contain errors
All trademarks and other things belong to their owners, if any.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c++


csiph-web