본문으로 건너뛰기 C++ Structured Bindings : Tuples, Maps, and auto

C++ Structured Bindings : Tuples, Maps, and auto

C++ Structured Bindings : Tuples, Maps, and auto

이 글의 핵심

C++17 structured bindings: decomposing tuple, pair, array, aggregates; auto&, const auto&; map iteration; pitfalls with temporaries; custom get protocol.

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

  1. Decompose tuple/array/struct-like types
  2. auto / auto& / const auto& control copies vs references
  3. for (const auto& [k,v] : map) is idiomatic
  4. Match element count; watch temporary lifetimes
  5. No runtime overhead inherent to bindings

Supported kinds

KindExample
Arrayint a[3]
Tuple / pairstd::tuple, std::pair
Aggregate structPlain structs with public data
CustomTuple protocol

Next steps


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


Frequently Asked Questions (FAQ)

Q. When would I use this in practice?

A. C++17 structured bindings: decomposing tuple, pair, array, aggregates; auto&, const auto&; map iteration; pitfalls.

Q. What should I read before this?

A. Follow the previous article or related articles links at the bottom of each post to learn in sequence. See the C++ series index for the full picture.

Q. Where can I study this more deeply?

A. Check cppreference and the relevant library’s official documentation. The reference links at the end of the article are also worth using.


Other articles related to this topic.


Keywords Covered in This Article (Related Search Terms)

This article covers C++, Structured Binding, C++17, auto, Decomposition.