August 9, 2025

std::pair and std::tuple in C++

Posted on August 9, 2025  •  5 minutes  • 963 words

When working with C++, sometimes you need to group multiple values together without creating a full-fledged struct or class. That’s where std::pair and std::tuple come in.

Both are part of the Standard Template Library (STL) and help store multiple elements in a single object — but they differ in flexibility and size.

In this blog, we’ll explore their syntax, features, and practical examples so you can use them effectively in your C++ projects.


YouTube video thumbnail

1. std::pair

Overview

std::pair is a container that holds exactly two values, possibly of different types.

Header file:

#include <utility>

Syntax:

std::pair<Type1, Type2> name;

1.1 Creating a Pair

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

int main() {
    pair<int, string> p1(1, "C++");
    pair<int, string> p2 = make_pair(2, "STL");

    cout << p1.first << " - " << p1.second << endl;
    cout << p2.first << " - " << p2.second << endl;
}

Output:

1 - C++
2 - STL

1.2 Accessing Elements

  • .first → Access first element

  • .second → Access second element

1.3 Modifying Pair Elements

pair<int, string> p(10, "Hello");
p.first = 20;
p.second = "World";

cout << p.first << ", " << p.second;

Output:

20, World

1.4 Comparing Pairs

Pairs are compared lexicographically:

  • Compare .first

  • If equal, compare .second

pair<int, int> a(1, 2);
pair<int, int> b(1, 3);

if (a < b) cout << "a is smaller";
else cout << "b is smaller";

Output:

a is smaller

1.5 Use Cases of std::pair

  • Returning two values from a function
  • Storing key-value pairs in std::map or std::unordered_map
  • Storing coordinates (x, y)
  • Sorting paired data

Example: Sorting Pairs

#include <vector>
#include <algorithm>
#include <iostream>

int main() 
{
    std::vector<std::pair<int, std::string>> v = { {2, "Two"}, {1, "One"}, {3, "Three"}};

    std::sort(v.begin(), v.end());

    for (auto &p : v)
        std::cout << p.first << " - " << p.second << std::endl;
}

Output

1 - One
2 - Two
3 - Three

2. std::tuple

Overview std::tuple is a generalization of std::pair — it can hold any number of elements of different types.

Header file:

#include <tuple>

Syntax:

std::tuple<Type1, Type2, Type3, ...> name;

2.1 Creating a Tuple

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

int main() {
    tuple<int, string, double> t1(1, "C++", 3.14);
    auto t2 = make_tuple(2, "STL", 2.71);

    cout << get<0>(t1) << " - " << get<1>(t1) << " - " << get<2>(t1) << endl;
    cout << get<0>(t2) << " - " << get<1>(t2) << " - " << get<2>(t2) << endl;
}
/*
Output:
1 - C++ - 3.14
2 - STL - 2.71
*/

2.2 Accessing and Modifying Elements

tuple<int, int, int> t(1, 2, 3);
get<1>(t) = 20;

cout << get<0>(t) << ", " << get<1>(t) << ", " << get<2>(t);

/*
Output:
1, 20, 3
*/

2.3 Tuple Size

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

int main() {
    tuple<int, char, double> t(1, 'A', 2.5);
    cout << "Tuple size: " << tuple_size<decltype(t)>::value;
}
// Output:
// Tuple size: 3

2.4 Unpacking Tuples

Using std::tie:

tuple<int, string, double> t(1, "Hello", 3.14);
int a; string b; double c;
tie(a, b, c) = t;

cout << a << ", " << b << ", " << c;

Using Structured Bindings (C++17+):

auto [x, y, z] = make_tuple(5, "World", 9.81);
cout << x << ", " << y << ", " << z;

2.5 Comparing Tuples

tuple<int, int, int> t1(1, 2, 3);
tuple<int, int, int> t2(1, 2, 4);

if (t1 < t2) cout << "t1 is smaller";
//Output:
//t1 is smaller

2.6 Concatenating Tuples

auto t1 = make_tuple(1, 2);
auto t2 = make_tuple(3, 4);
auto t3 = tuple_cat(t1, t2);

cout << get<0>(t3) << ", " << get<1>(t3) << ", "
     << get<2>(t3) << ", " << get<3>(t3);

// Output:
// 1, 2, 3, 4

3. Choosing Between std::pair and std::tuple

Feature std::pair std::tuple
Number of elements Always 2 Any number
Access style .first, .second get<index>
Readability Clear for 2 items Less descriptive for small pairs
Flexibility Limited Unlimited types

4. Practical Example

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

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

int main() 
{
    auto [mn, mx, sum] = getMinMaxSum(5, 1, 9);
    cout << "Min: " << mn << ", Max: " << mx << ", Sum: " << sum;
}
// Output : 
// Min: 1, Max: 9, Sum: 15

  • Use std::pair when you just need two related values.

  • Use std::tuple when you need to group more than two values or values of multiple types.

  • Both can be compared, unpacked, and returned from functions easily.

  • By mastering these STL types, you can write cleaner, more expressive C++ code without creating unnecessary structs or classes.


Quick reference (cheat-sheet)

  • Headers: #include <utility> (pair), #include <tuple> (tuple utilities), other headers as needed (e.g., <map>, <vector>, <algorithm>).
  • Pair access: .first, .second
  • Tuple access: std::get<Index>(t) or std::get<Type>(t) (type only if unique).
  • Unpacking: std::tie(...), structured bindings: auto [a,b] = ...; (C++17)
  • Combine tuples: std::tuple_cat(...)
  • Call callable from tuple: std::apply(callable, tuple) (C++17)
  • Piecewise construction (pair): std::piecewise_construct + std::forward_as_tuple(...)

C++ standard notes:

  • std::pair exists since earlier C++ (pre-C++11).
  • std::tuple, std::make_tuple, std::tie were introduced in C++11.
  • std::get<T> (get by type) is available in C++14 (requires unique type).
  • Structured bindings and std::apply require C++17.
  • std::make_from_tuple is also a C++17 utility.
Follow me

I work on everything coding and share developer memes