Skip to main content

C++ STL

tuple

Complete lesson for tuple using LEARNCODEGURU’s 6-level learning model — from basics to advanced practice, with C++ OOP and STL where relevant.

L1

Basics — tuple

Section: C++ STL. C++ std::tuple — store multiple values of mixed types, get/tie/structured bindings, and Tuple vs Pair.

What is a tuple?

  • std::tuple is a fixed-size collection of values that can have **different types**.
  • Unlike pair (exactly 2), a tuple can hold **0, 1, 2, 3, …** elements.
  • Access by compile-time index: get<0>(t), get<1>(t), …
  • Header: #include
  • **Real-life:** a sealed pack of mixed items — name, age, score — opened by position.
IdeaMeaning
tupleHeterogeneous fixed pack of values
get(t)Access element at index i
tuple_sizeNumber of elements (compile-time)
Structured bindingsauto [a,b,c] = t; (C++17)

Why use tuple?

  • Return **multiple** values from a function without inventing a struct yet.
  • Group related fields temporarily (x, y, z) or (ok, code, message).
  • Unpack with tie / structured bindings.
  • Prefer a named **struct** when fields need lasting, readable names.
BenefitExample
Multi-returntuple bounds()
Mixed typestuple
Unpacktie(a,b,c) = t; / auto [a,b,c]=t;
Generic codeTemplates over tuple_size / get

Differences between Tuple and Pair

  • Same family of “bundle values together” — different size and access style.
FeatureTuple (std::tuple)Pair (std::pair)
Element countAny number (N)Exactly 2
Accessget(t)first / second
Named membersNo — index onlyYes — first, second
Header
Createmake_tuple, bracesmake_pair, braces
Unpacktie, structured bindingsStructured bindings / first-second
std::ignoreYes with tieLess common pattern
Map element typeNot the map node typepair
Nested readabilityBetter than nested pairsNested pairs get messy
When to prefer3+ values, or generic NAlways exactly two fields

Creating a tuple

  • Direct type list, braced init, or make_tuple.
  • make_tuple deduces types from arguments.
  • forward_as_tuple (advanced) forwards references — for emplace-style APIs.
#include <iostream>
#include <string>
#include <tuple>
using namespace std;

int main() {
    tuple<string, int, double> a("x", 1, 2.5);
    tuple<string, int, double> b = {"y", 2, 3.5};
    auto c = make_tuple(10, 'A', true);

    cout << get<0>(a) << " " << get<1>(a) << " " << get<2>(a) << "\n";
    return 0;
}

Access with get and structured bindings

  • get(t) — index must be a **compile-time constant**.
  • C++17: auto [x, y, z] = t; is usually clearer.
  • tuple_size::value — how many elements.
#include <iostream>
#include <string>
#include <tuple>
using namespace std;

int main() {
    tuple<string, int, double> t = {"Ann", 20, 9.5};
    cout << get<0>(t) << "\n";

    auto [name, age, score] = t;
    cout << name << " " << age << " " << score << "\n";
    return 0;
}

tie — unpack into existing variables

  • std::tie(a, b, c) = t; assigns tuple elements into existing lvalues.
  • std::ignore skips a position: tie(a, ignore, c) = t;.
  • Older style still common; structured bindings often replace it for new locals.
#include <iostream>
#include <tuple>
using namespace std;

int main() {
    int x = 0, z = 0;
    auto t = make_tuple(10, 20, 30);
    tie(x, ignore, z) = t;
    cout << x << " " << z << "\n"; // 10 30
    return 0;
}

Returning multiple values

  • Return a tuple instead of multiple out-parameters.
  • Caller unpacks with structured bindings or tie.
#include <iostream>
#include <tuple>
using namespace std;

tuple<int, int, int> stats(int a, int b, int c) {
    int sum = a + b + c;
    int mn = min(a, min(b, c));
    int mx = max(a, max(b, c));
    return {sum, mn, mx};
}

int main() {
    auto [sum, mn, mx] = stats(3, 9, 1);
    cout << sum << " " << mn << " " << mx << "\n";
    return 0;
}

Comparison of tuples

  • Relational operators compare **lexicographically** left to right.
  • Same idea as pair, extended to N elements.
#include <iostream>
#include <tuple>
using namespace std;

int main() {
    auto a = make_tuple(1, 5, 9);
    auto b = make_tuple(1, 5, 10);
    cout << (a < b) << "\n"; // 1
    return 0;
}

Key points to remember

  • tuple = N mixed values; pair = exactly 2 with first/second.
  • Access with get or structured bindings.
  • tie + ignore unpack into existing variables.
  • Prefer a struct when names matter long-term.
  • Header .
L2

Advanced — tuple

tuple_cat and tuple_size

  • tuple_cat(t1, t2) concatenates tuples.
  • tuple_size_v (C++17) gives the element count.
#include <iostream>
#include <tuple>
using namespace std;

int main() {
    auto a = make_tuple(1, 2);
    auto b = make_tuple(3);
    auto c = tuple_cat(a, b); // 1,2,3
    cout << tuple_size_v<decltype(c)> << "\n"; // 3
    cout << get<2>(c) << "\n";
    return 0;
}

References in tuples

  • tie creates a tuple of **references** to existing variables.
  • make_tuple usually stores **values** (decays).
  • Be careful not to return references to locals via tuples.

Tuple vs struct

  • Tuple: quick, anonymous positions — great for temporary multi-return.
  • Struct: named fields, invariants, methods — better for lasting domain types.
  • Nested tuples of tuples hurt readability — name a type instead.
AspectTupleStruct
Field namesNoYes
AccessIndex / binding orderMember names
Best forShort-lived bundlesDomain models
Refactor safetyOrder-sensitiveNamed — clearer

apply (overview, C++17)

  • std::apply(f, t) calls f with tuple elements as arguments.
  • Handy in generic code; optional for beginners.

Design tips

  • 2 values → consider pair; 3+ → tuple or struct.
  • Document element order in a comment if you use tuple.
  • Prefer structured bindings over deep get<> chains.
  • Do not replace every struct with tuples — APIs become opaque.
L3

Tricky Interview Points

Q1) What is std::tuple?

Answer A fixed-size heterogeneous collection that can store any number of values of mixed types.

Q2) Tuple vs pair?

Answer pair always has two elements (first/second); tuple can have N elements accessed by get<i> or structured bindings.

Q3) How do you access tuple elements?

Answer std::get<index>(t), or C++17 structured bindings auto [a,b,c] = t;

Q4) What does std::tie do?

Answer Creates a tuple of references used to assign from another tuple into existing variables; ignore skips a slot.

Q5) Header for tuple?

Answer <tuple>

Q6) How does tuple comparison work?

Answer Lexicographically from the first element to the last.

Q7) When prefer a struct over a tuple?

Answer When fields need meaningful names, invariants, or a stable public API.

Q8) Can a tuple hold references?

Answer Yes — e.g. via tie or tuple<int&> — but lifetime must be valid.

Q9) What is make_tuple?

Answer A helper that constructs a tuple with types deduced from its arguments.

Q10) What is tuple_cat?

Answer A function that concatenates two or more tuples into one.

Q11) Is get index runtime variable?

Answer No — the index template argument must be known at compile time.

Q12) Typical use of tuple in interviews?

Answer Return multiple results from a function, or store mixed fields briefly before unpacking.

L4

Simple Programs

Create and get

#include <iostream>
#include <string>
#include <tuple>
using namespace std;

int main() {
    tuple<string, int, double> t = {"x", 1, 2.5};
    cout << get<0>(t) << " " << get<1>(t) << " " << get<2>(t) << "\n";
    return 0;
}

Structured bindings

#include <iostream>
#include <tuple>
using namespace std;

int main() {
    auto t = make_tuple(10, 20, 30);
    auto [a, b, c] = t;
    cout << a << " " << b << " " << c << "\n";
    return 0;
}

tie and ignore

#include <iostream>
#include <tuple>
using namespace std;

int main() {
    int a = 0, c = 0;
    tie(a, ignore, c) = make_tuple(1, 2, 3);
    cout << a << " " << c << "\n";
    return 0;
}

Return three values

#include <iostream>
#include <tuple>
using namespace std;

tuple<int, int, int> divmod(int n, int d) {
    return {n / d, n % d, d};
}

int main() {
    auto [q, r, d] = divmod(17, 5);
    cout << q << " " << r << " " << d << "\n";
    return 0;
}

tuple comparison

#include <iostream>
#include <tuple>
using namespace std;

int main() {
    cout << (make_tuple(1, 2, 3) < make_tuple(1, 2, 4)) << "\n";
    return 0;
}

tuple_cat

#include <iostream>
#include <tuple>
using namespace std;

int main() {
    auto t = tuple_cat(make_tuple(1, 2), make_tuple("hi"));
    cout << get<0>(t) << get<1>(t) << get<2>(t) << "\n";
    return 0;
}
L5

Problem Solving Tricks

  • tuple = N mixed values; pair = exactly two.
  • get(t) — i is compile-time.
  • auto [a,b,c] = t; for clear unpacking.
  • tie(a,b,c) = t; into existing variables.
  • ignore skips a tie slot.
  • Lexicographic comparisons left to right.
  • Prefer struct when names matter.
  • make_tuple deduces types.
  • tuple_cat concatenates packs.
  • Header .
  • Do not nest tuples deeply.
  • Tuple vs Pair table is a common interview ask.
L6

Practice Programs List

  1. Create tuple and print with get<>.
  2. Unpack with structured bindings.
  3. Use tie + ignore to assign first and third only.
  4. Write a function returning tuple of sum, min, max of three ints.
  5. Compare two 3-element tuples and explain the result.
  6. Concatenate two tuples with tuple_cat.
  7. Write Tuple vs Pair table in comments (8 rows).
  8. Write Tuple vs Struct table (5 rows).
  9. Store RGB as tuple; print each channel.
  10. Explain why get index cannot be a runtime variable.
  11. Refactor a nested pair-of-pairs into a tuple.
  12. List three APIs where multi-return via tuple helps.