70

Assume I have an object of type

std::map<std::string, std::tuple<int, float>> data;

Is it possible to access the element types in a nested way (i.e. when used in ranged for loop) like this

for (auto [str, [my_int, my_float]] : data) /* do something */
Timo
  • 9,269
  • 2
  • 28
  • 58
  • 1
    Have you tried it? – bipll Feb 28 '18 at 17:54
  • 1
    Yes I tried it. It doesn't work with the syntax above. Thats why I'm asking if it is even possible. – Timo Feb 28 '18 at 17:55
  • 1
    A problem is: how to tell C++ what const/reference-ness to use for each hidden object to which each nested set of introduced names are bound? The const/reference qualifier refers to said hidden object, not the introduced aliases to its members/`get()`. I can't see how it'd matter in this case if both were the same, nor immediately think of cases where distinct qualifiers would be needed, but I wouldn't want C++ to add in nested structured bindings if they were 2nd-class compared to what we currently have. And making them 1st-class seems perilous, when the grammar is probably already straining! – underscore_d Sep 16 '18 at 17:54

2 Answers2

43

No, it is not possible.

I distinctly remember reading somewhere that nested structured bindings are not allowed for C++17, but they are considering allowing it in a future standard. Can't find the source though.

bolov
  • 72,283
  • 15
  • 145
  • 224
  • I'm curious how the syntax will not clash with attributes if nested decompositions become a thing. – miradulo Feb 28 '18 at 18:03
  • 1
    Sad. That would have been one step closer to Python++. @miradulo I was asking the same question to myself. Are attributes even allowed after a type qualifier like `auto [[attribute]] [var1, var2]`? – Timo Feb 28 '18 at 18:05
  • 1
    @Timo Yup, take a look at the [cppref example](http://en.cppreference.com/w/cpp/language/attributes). Attributes can be almost anywhere. – miradulo Feb 28 '18 at 18:13
  • 1
    @miradulo Maybe extra tailing comma? Like auto [[a,b],] = func(); – LIU Qingyuan Feb 21 '20 at 12:56
29

No, they aren't possible; but this is:

for (auto&& [key, value] : data) {
  auto&& [my_int, my_float] = value;
}

which is close at least.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • 1
    Yes that's how I'm doing it now. Thanks. – Timo Mar 01 '18 at 12:26
  • (Just out of curiosity for something I didn't understand 100% yet:) What is the benefit of using universal refs here? Aren't `data` and `value` l-values, so that these universal refs will result in being l-value refs in the end anyway? – kaba Feb 08 '21 at 15:20
  • 1
    @kaba I am lazy, and use either `auto&&` if I don't care, `auto const&` when I want to block modification, `auto&` when I want to modify what I'm iterating over, and `auto` when I want a copy I can modify and not impact the original sequence. Here, I don't care, so I use `auto&&`; `auto&&` to me means "I do not care how this is stored -- alias or copy or whatever". – Yakk - Adam Nevraumont Feb 08 '21 at 17:08