C++ Structured Bindings (C++17): Tuples, Maps, and auto [a,b]
이 글의 핵심
Structured bindings unpack tuples, pairs, arrays, and structs into named variables—map loops, minmax_element, insert results, with lifetime and count rules.
Introduction
Structured bindings (C++17) let you decompose tuples, arrays, structs, and similar types into separate names.
#include <tuple>
#include <iostream>
#include <string>
int main() {
std::tuple<int, double, std::string> t = {42, 3.14, "Hello"};
auto [i, d, s] = t;
std::cout << i << std::endl;
std::cout << d << std::endl;
std::cout << s << std::endl;
}
Why use them:
- Concise multi-variable declarations
- Readable names in loops
- Safer type deduction
- Convenient for maps and multi-return APIs
std::map<std::string, int> m;
for (const auto& [key, value] : m) {
std::cout << key << ": " << value << '\n';
}
1. Basics
Arrays
int arr[] = {1, 2, 3};
auto [a, b, c] = arr;
Structs
struct Point {
int x;
int y;
};
Point p = {10, 20};
auto [x, y] = p;
Tuples / returns
std::tuple<int, double, std::string> getData() {
return {42, 3.14, "Hello"};
}
int main() {
auto [i, d, s] = getData();
}
2. References and const
struct Point {
int x, y;
};
int main() {
Point p = {10, 20};
auto [x1, y1] = p; // copies
auto& [x2, y2] = p; // aliases
const auto& [x3, y3] = p;
x2 = 100; // modifies p.x
}
3. Practical examples
Map iteration
std::map<std::string, int> scores = {
{"Alice", 90},
{"Bob", 85},
{"Charlie", 95}
};
for (const auto& [name, score] : scores) {
std::cout << name << ": " << score << std::endl;
}
Multiple return values
std::tuple<int, int, int> getRGB() {
return {255, 128, 64};
}
std::pair<int, int> divmod(int dividend, int divisor) {
return {dividend / divisor, dividend % divisor};
}
int main() {
auto [r, g, b] = getRGB();
auto [quotient, remainder] = divmod(17, 5);
}
minmax_element / insert
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
auto [minIt, maxIt] = std::minmax_element(v.begin(), v.end());
std::map<std::string, int> m;
auto [it, inserted] = m.insert({"key", 10});
Structs in vectors
struct Person {
std::string name;
int age;
double height;
};
std::vector<Person> people = {
{"Alice", 25, 165.5},
{"Bob", 30, 175.0}
};
for (const auto& [name, age, height] : people) {
std::cout << name << " (" << age << ", " << height << ")\n";
}
4. Common pitfalls
Count mismatch
The number of names must match the tuple/struct size.
Lifetime: reference to subobject of temporary
// Dangerous
// auto& [x, y] = Point{10, 20};
// Safe: copy
auto [x1, y1] = Point{10, 20};
// Safe: bind to named variable
Point p = {10, 20};
auto& [x2, y2] = p;
No explicit types in the binding list
Use auto (or structured binding with auto& / const auto&); you cannot write auto [int x, double y] = ....
5. Patterns
Error handling with pair
std::pair<bool, std::string> parseConfig(const std::string& path) {
std::ifstream file(path);
if (!file.is_open()) {
return {false, "missing file"};
}
return {true, "ok"};
}
int main() {
auto [ok, msg] = parseConfig("config.json");
if (!ok) {
std::cerr << msg << std::endl;
return 1;
}
}
Range-for modifying values
std::map<std::string, std::vector<int>> data = {
{"A", {1, 2, 3}},
{"B", {4, 5, 6}}
};
for (auto& [key, values] : data) {
values.push_back(0);
}
6. Custom types (tuple protocol)
Implement get<I>(), specialize std::tuple_size / std::tuple_element, then auto [a,b] = myObj works.
7. Student grouping example
See Korean article for full Student / groupByGrade / printStatistics example—same logic in English prose.
Summary
Highlights
- Decompose tuple/array/struct-like types
auto/auto&/const auto&control copies vs referencesfor (const auto& [k,v] : map)is idiomatic- Match element count; watch temporary lifetimes
- No runtime overhead inherent to bindings
Supported kinds
| Kind | Example |
|---|---|
| Array | int a[3] |
| Tuple / pair | std::tuple, std::pair |
| Aggregate struct | Plain structs with public data |
| Custom | Tuple protocol |
Next steps
- Tuple
- Range-based for
- auto
Related posts (internal links)
- Structured bindings advanced
- Range-based for + bindings (series)
- tuple apply
Practical tips
Debugging
- Warnings first
Performance
- Profile
Code review
- Conventions
Practical checklist
Before coding
- Right approach?
- Maintainable?
- Performance?
While coding
- Warnings?
- Edge cases?
- Errors?
At review
- Intent?
- Tests?
- Docs?
Keywords
C++, structured binding, C++17, auto, destructuring
Related posts
- Range-based for + bindings
- Structured bindings advanced
- any
- auto keyword
- auto type deduction