Banyak algoritma DSA perlu mengelompokkan beberapa nilai menjadi satu entitas — pasangan key-value, triplet (node, dist, parent), atau kumpulan multi-field. STL menyediakan std::pair (dua nilai) dan std::tuple (n nilai). Sejak C++17, structured binding auto [a, b] = pair mengurai tipe komposit menjadi variabel terpisah dengan sintaks ringkas. Pada Chapter ini kita akan mendemonstrasikan pembuatan, pengaksesan, dan penguraian pair/tuple, lalu menutup dengan pola idiomatik std::tie untuk comparator multi-kriteria.

Tipe Komposit Utama #

TipeJumlah elemenAkses
std::pair<T1, T2>2.first, .second atau std::get<N>
std::tuple<T1, T2, ..., Tn>nstd::get<N>(t) atau std::get<T>(t)
std::array<T, N>Narr[i] atau structured binding

Mekanisme: Structured Binding (C++17) #

Sintaks auto [a, b, c] = expr; mengurai tipe komposit menjadi variabel individual. Tergantung tipe expr, tiga kasus:

  1. Tuple-like (std::pair, std::tuple, std::array): mengikuti std::tuple_size dan std::get<N>.
  2. Aggregate (struct/class dengan member publik): membongkar member berurutan.
  3. Array C-style: membongkar elemen per indeks.

Mode binding:

  • auto [a, b] = expr — copy nilai.
  • auto& [a, b] = expr — referensi (mengikat ke elemen asli).
  • const auto& [a, b] = expr — referensi const.

Kode: Sembilan Demo Pair/Tuple #

cpp
#include <iostream>
#include <utility>
#include <tuple>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

// Mengembalikan banyak nilai via tuple
std::tuple<int, int, double> stats(const std::vector<int>& v) {
    int mn = v.front(), mx = v.front();
    long long sum = 0;
    for (int x : v) {
        if (x < mn) mn = x;
        if (x > mx) mx = x;
        sum += x;
    }
    return {mn, mx, static_cast<double>(sum) / v.size()};
}

int main() {
    // 1) std::pair
    std::pair<int, std::string> p1{1, "alice"};
    std::cout << "pair: " << p1.first << " -> " << p1.second << '\n';

    // make_pair
    auto p2 = std::make_pair(2, std::string{"bob"});
    std::cout << "pair: " << p2.first << " -> " << p2.second << '\n';

    // 2) Structured binding untuk pair (C++17)
    auto [id, name] = p1;
    std::cout << "destructured: id=" << id << ", name=" << name << '\n';

    // 3) std::tuple
    std::tuple<int, std::string, double> t{42, "answer", 3.14};
    std::cout << "tuple: " << std::get<0>(t) << ", "
              << std::get<1>(t) << ", " << std::get<2>(t) << '\n';

    // 4) Structured binding untuk tuple
    auto [a, b, c] = t;
    std::cout << "destructured tuple: " << a << ", " << b << ", " << c << '\n';

    // 5) Structured binding dari fungsi
    std::vector<int> v = {4, 1, 9, 2, 7, 5};
    auto [mn, mx, avg] = stats(v);
    std::cout << "stats: min=" << mn << ", max=" << mx << ", avg=" << avg << '\n';

    // 6) Structured binding untuk iterasi map
    std::map<std::string, int> m = {{"alice", 90}, {"bob", 75}, {"carol", 88}};
    std::cout << "map entries:\n";
    for (const auto& [key, value] : m) {
        std::cout << "  " << key << " -> " << value << '\n';
    }

    // 7) std::tie — unpack tuple ke variabel yang sudah ada
    int x, y;
    std::string z;
    std::tie(x, y, z) = std::make_tuple(10, 20, std::string{"hello"});
    std::cout << "tie: " << x << ' ' << y << ' ' << z << '\n';

    // 8) std::tie untuk comparator multi-kriteria
    struct Item { int p; int d; std::string n; };
    auto cmp_items = [](const Item& a, const Item& b) {
        return std::tie(a.p, a.d, a.n) < std::tie(b.p, b.d, b.n);
    };
    std::vector<Item> items = {{3, 2, "c"}, {1, 5, "a"}, {3, 1, "b"}, {1, 5, "b"}};
    std::sort(items.begin(), items.end(), cmp_items);
    std::cout << "sorted items:\n";
    for (const auto& it : items) {
        std::cout << "  p=" << it.p << " d=" << it.d << " n=" << it.n << '\n';
    }

    // 9) Structured binding untuk array C-style
    int arr[3] = {10, 20, 30};
    auto [g1, g2, g3] = arr;
    std::cout << "arr: " << g1 << ' ' << g2 << ' ' << g3 << '\n';

    return 0;
}

Output yang Dihasilkan:

text
pair: 1 -> alice
pair: 2 -> bob
destructured: id=1, name=alice
tuple: 42, answer, 3.14
destructured tuple: 42, answer, 3.14
stats: min=1, max=9, avg=4.66667
map entries:
  alice -> 90
  bob -> 75
  carol -> 88
tie: 10 20 hello
sorted items:
  p=1 d=5 n=a
  p=1 d=5 n=b
  p=3 d=1 n=b
  p=3 d=2 n=c
arr: 10 20 30

Bedah Kode Baris-per-Baris #

  1. std::pair<int, std::string> p1{1, "alice"};: pair dengan tipe berbeda — int dan std::string. Akses member lewat .first dan .second.
  2. std::make_pair(2, std::string{"bob"}): deduksi tipe otomatis. Tanpa std::string{} eksplisit, string literal "bob" menjadi const char* — pair tipenya pair<int, const char*> (sering tidak diinginkan).
  3. auto [id, name] = p1;: structured binding copy. id adalah int, name adalah std::string — keduanya salinan nilai dari p1. Memodifikasi id/name tidak memengaruhi p1.
  4. std::tuple<int, std::string, double> t{...}: tuple tiga elemen heterogen. Akses via std::get<N>(t) dengan indeks compile-time.
  5. auto [a, b, c] = t;: structured binding untuk tuple. Jumlah variabel harus cocok dengan std::tuple_size<Tuple>::value (di sini 3).
  6. return {mn, mx, static_cast<double>(sum) / v.size()};: tuple bisa dibuat dari braced-init-list. Fungsi stats mengembalikan (min, max, average) — pola idiomatik untuk multiple return values.
  7. for (const auto& [key, value] : m): structured binding pada range-for. Setiap iterasi mengurai std::pair<const std::string, int> menjadi dua variabel. const auto& menghindari copy pair (string mahal dicopy).
  8. std::tie(x, y, z) = std::make_tuple(10, 20, "hello");: std::tie membuat tuple referensi. Saat di-assign, nilai elemen tuple kanan disalin ke variabel yang ditunjuk referensi. Berguna bila variabel sudah dideklarasikan sebelumnya.
  9. std::tie(a.p, a.d, a.n) < std::tie(b.p, b.d, b.n): idiomatik comparator multi-kriteria. std::tie membuat tuple referensi, lalu operator< tuple membandingkan secara lexicographic. Output sorted: ascending by (p, d, n). Bandingkan dengan penulisan manual if (a.p != b.p) return a.p < b.p; if (a.d != b.d) return a.d < b.d; return a.n < b.n; — tie jauh lebih ringkas.
  10. auto [g1, g2, g3] = arr;: structured binding untuk array C-style int[3]. Jumlah variabel harus cocok dengan ukuran array.

Pola Umum di DSA #

Multiple Return Values #

cpp
auto divmod = [](int a, int b) -> std::pair<int, int> {
    return {a / b, a % b};
};
auto [q, r] = divmod(17, 5);   // q=3, r=2

Edge Representation (Graph) #

cpp
using Edge = std::tuple<int, int, int>;  // (from, to, weight)
std::vector<Edge> edges = {{0, 1, 5}, {1, 2, 3}};
for (auto [u, v, w] : edges) { /* ... */ }

Iterasi Map dengan Key dan Value #

cpp
for (const auto& [k, v] : m) {
    std::cout << k << " -> " << v << '\n';
}

Sorting Multi-Kriteria via std::tie #

cpp
std::sort(v.begin(), v.end(), [](const auto& a, const auto& b) {
    return std::tie(a.priority, a.deadline, a.name)
         < std::tie(b.priority, b.deadline, b.name);
});

Ringkasan #

  • std::pair<T1, T2> untuk dua nilai heterogen; akses .first/.second.
  • std::tuple<T1, ..., Tn> untuk n nilai; akses std::get<N>.
  • C++17 structured binding auto [a, b] = expr mengurai pair/tuple/array/aggregate — copy bila auto, referensi bila auto&.
  • std::tie membuat tuple referensi — idiomatik untuk comparator multi-kriteria dan unpack ke variabel yang sudah ada.
  • Untuk multiple return values, kembalikan std::tuple lalu uraikan dengan structured binding.
  • Iterasi map dengan for (const auto& [k, v] : m) adalah idiom modern — ringkas dan efisien.