ReviseAlgo Logo

Standard Template Library (STL)

std::pair and std::tuple

Lightweight heterogeneous aggregates for grouping multiple values

Interview: Ubiquitous in interview solutions — returning multiple values, map entries, priority queue elements

std::pair and std::tuple

std::pair<T1, T2> groups exactly two values; std::tuple<Ts...> groups any number. Both are value types — copyable, movable, comparable. They're used throughout the STL: map iterators return pair<const Key, Value>, and structured bindings (C++17) make working with them cleaner than ever.

Structured Bindings (C++17)

C++17 structured bindings decompose pairs and tuples cleanly: auto [x, y] = myPair; or auto [a, b, c] = myTuple;. This replaces verbose .first/.second and get<0>() syntax. Use structured bindings when iterating map entries: for (auto& [key, val] : map).

Returning Multiple Values

Tuple is the standard way to return multiple values without defining a struct. Since C++17, structured bindings make this idiomatic: auto [min, max, sum] = analyze(data);. For clarity in APIs, prefer a named struct over tuple when the return type has semantic meaning — tuple provides no names for its elements.

Interview Corner

Q: How does pair comparison work in a priority queue with custom ordering?

A: pair comparison is lexicographic — first compares the first elements; if equal, compares second. For Dijkstra's algorithm, store (distance, node) pairs in a min-heap: priority_queue<pair<int,int>, vector<pair<int,int>>, greater<>>. The pair's lexicographic comparison naturally sorts by distance first (the primary key), then by node ID as a tiebreaker.

Common Pitfalls

  • Using get<n> with wrong index: get<n>(tuple) — n must be a compile-time constant less than the tuple size. Runtime index access isn't directly supported.
  • Naming semantics: pair.first and pair.second have no semantic meaning — use a named struct for APIs where clarity matters.

Best Practices

  • Use make_pair() / make_tuple() or CTAD (C++17) for construction: pair p{1, "hello"};
  • Prefer structured bindings when decomposing pairs/tuples — auto [k, v] = *it; is clearer than auto k = it->first; auto v = it->second;