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::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)
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::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.