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 #
| Tipe | Jumlah elemen | Akses |
|---|---|---|
std::pair<T1, T2> | 2 | .first, .second atau std::get<N> |
std::tuple<T1, T2, ..., Tn> | n | std::get<N>(t) atau std::get<T>(t) |
std::array<T, N> | N | arr[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:
- Tuple-like (
std::pair,std::tuple,std::array): mengikutistd::tuple_sizedanstd::get<N>. - Aggregate (struct/class dengan member publik): membongkar member berurutan.
- 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 30Bedah Kode Baris-per-Baris #
std::pair<int, std::string> p1{1, "alice"};: pair dengan tipe berbeda —intdanstd::string. Akses member lewat.firstdan.second.std::make_pair(2, std::string{"bob"}): deduksi tipe otomatis. Tanpastd::string{}eksplisit, string literal"bob"menjadiconst char*— pair tipenyapair<int, const char*>(sering tidak diinginkan).auto [id, name] = p1;: structured binding copy.idadalahint,nameadalahstd::string— keduanya salinan nilai darip1. Memodifikasiid/nametidak memengaruhip1.std::tuple<int, std::string, double> t{...}: tuple tiga elemen heterogen. Akses viastd::get<N>(t)dengan indeks compile-time.auto [a, b, c] = t;: structured binding untuk tuple. Jumlah variabel harus cocok denganstd::tuple_size<Tuple>::value(di sini 3).return {mn, mx, static_cast<double>(sum) / v.size()};: tuple bisa dibuat dari braced-init-list. Fungsistatsmengembalikan(min, max, average)— pola idiomatik untuk multiple return values.for (const auto& [key, value] : m): structured binding pada range-for. Setiap iterasi menguraistd::pair<const std::string, int>menjadi dua variabel.const auto&menghindari copy pair (string mahal dicopy).std::tie(x, y, z) = std::make_tuple(10, 20, "hello");:std::tiemembuat tuple referensi. Saat di-assign, nilai elemen tuple kanan disalin ke variabel yang ditunjuk referensi. Berguna bila variabel sudah dideklarasikan sebelumnya.std::tie(a.p, a.d, a.n) < std::tie(b.p, b.d, b.n): idiomatik comparator multi-kriteria.std::tiemembuat tuple referensi, laluoperator<tuple membandingkan secara lexicographic. Output sorted: ascending by(p, d, n). Bandingkan dengan penulisan manualif (a.p != b.p) return a.p < b.p; if (a.d != b.d) return a.d < b.d; return a.n < b.n;—tiejauh lebih ringkas.auto [g1, g2, g3] = arr;: structured binding untuk array C-styleint[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; aksesstd::get<N>.- C++17 structured binding
auto [a, b] = exprmengurai pair/tuple/array/aggregate — copy bilaauto, referensi bilaauto&. std::tiemembuat tuple referensi — idiomatik untuk comparator multi-kriteria dan unpack ke variabel yang sudah ada.- Untuk multiple return values, kembalikan
std::tuplelalu uraikan dengan structured binding. - Iterasi map dengan
for (const auto& [k, v] : m)adalah idiom modern — ringkas dan efisien.