What are use cases for structured bindings?
Barring evidence to the contrary, I think Structured Bindings are merely a vehicle to deal with legacy API. IMHO, the APIs which require SB should have been fixed instead.
So, instead of
auto p = map.equal_range(k);
for (auto it = p.first; it != p.second; ++it)
doSomethingWith(it->first, it->second);
we should be able to write
for (auto &e : map.equal_range(k))
doSomethingWith(e.key, e.value);
Instead of
auto r = map.insert({k, v});
if (!r.second)
*r.first = v;
we should be able to write
auto r = map.insert({k, v});
if (!r)
r = v;
etc.
Sure, someone will find a clever use at some point, but to me, after a year of knowing about them, they are still an unsolved mystery. Esp. since the paper is co-authored by Bjarne, who's not usually known for introducing features that have such a narrow applicability.
Can you provide some other, possibly less obvious use cases for structured bindings? How else can they improve readability or even performance of C++ code?
More in general, you can use it to (let me say) unpack a structure and fill a set of variables out of it:
struct S { int x = 0; int y = 1; };
int main() {
S s{};
auto [ x, y ] = s;
(void)x, void(y);
}
The other way around would have been:
struct S { int x = 0; int y = 1; };
int main() {
S s{};
auto x = s.x;
auto y = s.y;
(void)x, void(y);
}
The same is possible with arrays:
int main() {
const int a[2] = { 0, 1 };
auto [ x, y ] = a;
(void)x, void(y);
}
Anyway, for it works also when you return the structure or the array from a function, probably you can argue that these examples belong to the same set of cases you already mentioned.
Another good example mentioned in the comments to the answer by @TobiasRibizel is the possibility to iterate through containers and unpack easily the contents.
As an example based on std::map
:
#include <map>
#include <iostream>
int main() {
std::map<int, int> m = {{ 0, 1 }, { 2, 3 }};
for(auto &[key, value]: m) {
std::cout << key << ": " << value << std::endl;
}
}
Can you provide some other, possibly less obvious use cases for structured bindings?
They can be used to implement get<N>
for structs - see magic_get
's automatically generated core17_generated.hpp
. This is useful because it provides a primitive form of static reflection (e.g. iterate over all members of a struct
).