What is ({}) called in C++?
Asked Answered
N

2

21

I just read code like this:

auto value = ({
  auto it = container.find(key);
  it != container.end() ? it->second : default_value;
});

What is this ({}) called? I don't think I've ever seen this before.

Northcliffe answered 12/8, 2023 at 19:38 Comment(7)
It is a gcc extension IIRC. not standard C++.Bogan
Doesn't compile for me, even when I add sensible definitions for key and container. Could you supply an example without any missing parts?Unspeakable
It is a compiler extension gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.htmlFumble
default is a keyword. Even if the statement expression is removed, how can it compile it != container.end() ? it->second : default;?Replication
Better question: How is this not standard yet? It's been available in Rust for ages now, albeit with less silly syntax.Passel
Funny that we just had a C version of this also hit Hot Network Questions a couple days ago: Using comma operator (a, b) when a is a block of codeFitzger
Duplicate of https://mcmap.net/q/94758/-are-compound-statements-blocks-surrounded-by-parens-expressions-in-ansi-c/1708801 ?Concentration
B
29

It is a gcc extension, so not standard C++,

it is statement expression.

Since C++11, you might use Immediately Invoked Function Expressions (IIFE) with lambda instead in most cases:

auto value = [&](){
  auto it = container.find(key);
  return it != container.end() ? it->second : default_value;
}();
Bogan answered 12/8, 2023 at 19:43 Comment(2)
It is still not the same as lambdas since a return in statement expressions returns from the enclosing function and not the statement expression.Oftentimes
@Daniel: And similarly with break/continue...Skurnik
I
11

Even before C89 was published, the authors of gcc invented an extension called a "statement expression" which would have been a useful part of the Standard language. It takes a compound statement whose last statement is an expression, and executes everything therein, and then treats the value of the last expression as the value of the statement expression as a whole.

While some other compilers have options to support such gcc extensions, the Standard's refusal to recognize features that aren't widely use, combined with programmers' reluctance to use features that aren't recognized by the Standard, have created a decades-long "chicken and egg" problem.

Impetrate answered 12/8, 2023 at 19:50 Comment(9)
You could've mentioned a full capture lambda as did Jarod.Varletry
@Varletry C89 doesn't have those, either ;-pMasinissa
@Masinissa yes, but in 2023, lambda is a well-known term. And the behaviour of the provided syntax fits within the definition of lambda. Some unnamed thing has existed from long decades ago; but now we know the name and should spell it.Varletry
@Red.Wave: It's not equivalent to a lambda, however. Specifically, the behavior of flow-control statements (break, continue, and return) is different between the two, because a lambda creates a completely new and distinct function scope while a statement expression is "just" one more statement of the enclosing function scope.Skurnik
@MatthieuM. It meets the very basic definition of lambda. A modern C++ lambda just happens to be a bit more restricted.Varletry
@Red.Wave: A lambda decomposes into a function pointer object which may be invoked from arbitrary context. A statement expression is essentially syntactic sugar for subdividing an expression into pieces which set the values of temporary objects, and then using those objects in the context where they are set.Impetrate
@Impetrate no. That's your interpretation of a C++ lambda. A Lambda - of any form - is more than syntax suger. One major advantage lambda is the optimization possibilities it creates. Any extension to the language (core or library, std or not) is too expensive to be just syntactically pretty; Performance often takes precedence. Lambda is a very generic and abstract term; in the modern C++, it has specifications, but the more generic definition covers the gcc extension too.Varletry
//Any extension to the language (core or library, std or not) is too expensive to be just syntactically pretty// You mean like double-slash comments? Especially when one factors in the way macros are processed in C, the syntactic sugar can offer substantial semantic benefits at the source-code level. For example, many processes could benefit greatly if C had a compound statement __once_and_then(someType x=y; z) which would initialize x, process the following, and then evaluate z, which could be used to do things like acquire a lock, perform an action, and release the lock...Impetrate
...without requiring that the source code contain a declaration for the object used to hold the lock. One could do that with a for loop and a dummy flag, but the amount of compiler logic necessary to avoid generating extra machine code for that would be greater than the amount required to handle __once_and_then.Impetrate

© 2022 - 2024 — McMap. All rights reserved.