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.
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::pairwhen you just need two related values. -
Use
std::tuplewhen 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)orstd::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::pairexists since earlier C++ (pre-C++11).std::tuple,std::make_tuple,std::tiewere introduced in C++11.std::get<T>(get by type) is available in C++14 (requires unique type).- Structured bindings and
std::applyrequire C++17.std::make_from_tupleis also a C++17 utility.