본문으로 건너뛰기
Previous
Next
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


자주 묻는 질문 (FAQ)

Q. 이 내용을 실무에서 언제 쓰나요?

A. C++17 structured bindings: decomposing tuple, pair, array, aggregates; auto&, const auto&; map iteration; pitfalls with … 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.

Q. 선행으로 읽으면 좋은 글은?

A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.

Q. 더 깊이 공부하려면?

A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.


같이 보면 좋은 글 (내부 링크)

이 주제와 연결되는 다른 글입니다.


이 글에서 다루는 키워드 (관련 검색어)

C++, Structured Binding, C++17, auto, Decomposition 등으로 검색하시면 이 글이 도움이 됩니다.