57

I found the original proposal for *C++ structured bindings here. It proposes a way to easily bind multiple return values, i.e.:

auto {a, b} = minmax(data);

But now I see that everyone points to the C++17/C++1z proposal syntax of

auto [a, b] = minmax(data);

Now that I learned "lists are written { like, this }" there comes a new list-syntax? Why? What is the problem with curly braces here?

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
towi
  • 21,587
  • 28
  • 106
  • 187
  • 2
    Usually quirky changes like that have to do with simplifying life for the parsers. – Yakk - Adam Nevraumont Oct 30 '16 at 19:59
  • 10
    One problem with braces is that braces until now delimit scopes, and here they wouldn't. By contrast, you can think of the square brackets like in a lambda capture list, and it works out reasonably nicely. – Kerrek SB Oct 30 '16 at 20:00
  • 3
    Note: There is no C++17 yet. C++17 is still being worked on. What will and what won't be in it, and in what form, won't be known for sure at least until February. – Kerrek SB Oct 30 '16 at 20:02
  • 2
    We do have a few NB comments requesting `{}`, so we'll see... – T.C. Oct 30 '16 at 20:22
  • "*Now that I learned "lists are written { like, this }" there comes a new list-syntax? Why?*" It's not a list. Well, it's not a list of *values*; it's a sequence of *names*. It's a different thing from a list of values, so why should it not be a different syntax? – Nicol Bolas Oct 30 '16 at 22:19
  • 4
    Chandler Carruth's answer to this question: https://youtu.be/430o2HMODj4?t=15m50s – Sebastian Wahl Mar 30 '17 at 09:20
  • @KerrekSB but that's wrong, as braces have been used for other things since at least 2011, when uniform initialisation and `initializer_list` were added. – underscore_d May 21 '17 at 16:56
  • @underscore_d: Sure, those braces also exist in C for aggregate initialziation. But they never introduce names, so they're not relevant as far as scoping is concerned. (But indeed that's a type of braces I had forgotten about in the previous comment.) – Kerrek SB May 21 '17 at 17:00

5 Answers5

24

The National Bodies from Spain and US have proposed to change back to the {} syntax because (P0488R0):

The “structured bindings” proposal originally used braces “{}” to delimit binding identifiers. Those delimiters were changed to brackets “[]” under the assertion that they didn’t introduce any syntactic problem. However, they turned out to introduce syntactic ambiguity with attributes and lambdas. In the light of various suggested fixes, it appears the original syntax is more adequate.

Therefore, there still remains the possibility of ending up having the original syntax for C++17 (which I strongly believe is preferred by most users).


Update from this trip report:

The original proposal for decomposition declarations used the syntax auto {a, b, c}; that was changed at the last meeting to auto [a, b, c]. This change was fairly controversial, and several comments asked to change it back to {} (while others encouraged keeping the []). There are technical arguments on both sides (the [] syntax can conflict with attributes once you start allowing nested decompositions; the {} syntax can conflict with uniform initialization if you throw Concepts into the mix and allow using a concept-name instead of auto), so in the end it’s largely a matter of taste. The clang implementers did report that they tried both, and found the ambiguities to be easier to work around with []. In the end, there was no consensus for a change, so the status quo ([] syntax) remains.

metalfox
  • 6,301
  • 1
  • 21
  • 43
  • Though I neither agree nor disagree with the desire to change the delimiters back to the original syntax, I do find it funny that one of the NBs described the change as sudden or last minute when it was made several revisions ago. – Mikel F Nov 03 '16 at 19:03
  • 1
    @MikelF In addition to ES and US, there is also a related comment from GB: “Nested decomposition declarations can’t work, as they clash with the attribute syntax” – metalfox Nov 04 '16 at 07:50
21

This is still under debate. It's difficult to be certain which syntax will be least confusing given how many uses there are for [] and {} already.

There's also the risk that "least confusing" and "easiest to parse" will be in conflict.

Jon Chesterfield
  • 2,251
  • 1
  • 20
  • 30
17

@SebastianWahl only commented with a link. I will quickly summarize the content behind the link.

Chandler Carruth's answer to this question: youtu.be/430o2HMODj4?t=15m50s

auto [a,b,c] = f();

is ok with auto. But you can also do this:

tuple<int,float,string> [a,b,c] = f();

So when you use {...} this would become

tuple<int,float,string> {a,b,c} = f();  //<<< not C++17

which is bad, because the piece tuple<int,float,string> {a,b,c} also has a meaning in C++ and thus would be a difficult ambiguity, difficult to solve.

towi
  • 21,587
  • 28
  • 106
  • 187
  • Perhaps `tuple [a,b,c] = f();` was supposed to be ok at some point - but it isn't in the released version of C++17 (or later releases) – Ted Lyngmo Jan 04 '23 at 07:58
11

The change from {} to [] occurred after Jacksonville and was made in response to comments from that meeting. This is detailed in p0144r2, which states: "because it is more visually distinct from the existing syntax for declaring multiple variables of the same type."

It appears that the NB comments requesting a change to the original usage of {} did not increase consensus in the Nov 2016 meetings, leaving the [] usage intact. At least until the Spring meeting.

Mikel F
  • 3,567
  • 1
  • 21
  • 33
4

One thing to be said for the square brackets syntax is that it closely resembles lambda capture clauses, where, similarly, you don't specify the variable type, since auto is implied. I.e.

auto func = [a, b] {}
auto func = [a=1, b=2.0] {}

It's obviously not the exact same thing, but when you think about it as "syntax for auto capturing by making sense of the context," it can work:

auto [a, b] = std::make_pair(1, 2.0);
Yam Marcovic
  • 7,953
  • 1
  • 28
  • 38