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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Hesky Fisher
  • 1,145
  • 7
  • 14
  • 9
    It is a gcc extension IIRC. not standard C++. – Jarod42 Aug 12 '23 at 19:42
  • 1
    Doesn't compile for me, even when I add sensible definitions for `key` and `container`. Could you supply an example without any missing parts? – john Aug 12 '23 at 19:42
  • 3
    It is a compiler extension https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html – n. m. could be an AI Aug 12 '23 at 19:42
  • `default` is a keyword. Even if the statement expression is removed, how can it compile `it != container.end() ? it->second : default;`? – 273K Aug 12 '23 at 20:01
  • Better question: How is this *not* standard yet? It's been available in Rust for ages now, albeit with less silly syntax. – Silvio Mayolo Aug 13 '23 at 21:39
  • 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 code](https://stackoverflow.com/q/76866848) – Peter Cordes Aug 14 '23 at 03:22
  • Duplicate of https://stackoverflow.com/q/1238016/1708801 ? – Shafik Yaghmour Aug 17 '23 at 13:15

2 Answers2

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;
}();
Jarod42
  • 203,559
  • 14
  • 181
  • 302
12

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.

supercat
  • 77,689
  • 9
  • 166
  • 211
  • 1
    You could've mentioned a full capture lambda as did Jarod. – Red.Wave Aug 13 '23 at 09:49
  • 1
    @Red.Wave C89 doesn't have those, either ;-p – SamB Aug 14 '23 at 02:44
  • @SamB 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. – Red.Wave Aug 14 '23 at 08:58
  • @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. – Matthieu M. Aug 14 '23 at 09:28
  • @MatthieuM. It meets the very basic definition of lambda. A modern C++ lambda just happens to be a bit more restricted. – Red.Wave Aug 14 '23 at 09:30
  • @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. – supercat Aug 14 '23 at 14:58
  • @supercat 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. – Red.Wave Aug 14 '23 at 15:08
  • //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... – supercat Aug 14 '23 at 17:05
  • ...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`. – supercat Aug 14 '23 at 17:08