Is there a difference between an std::pair
and an std::tuple
with only two members? (Besides the obvious that std::pair
requires two and only two members and tuple
may have more or less...)

- 44,692
- 7
- 66
- 118

- 10,297
- 11
- 59
- 88
6 Answers
There are some differences:
std::tuple
is not required by the standard to ever be standard-layout. Everystd::pair<T, Y>
is standard-layout if bothT
andY
are standard-layout.It's a bit easier to get the contents of a
pair
than atuple
. You have to use a function call in thetuple
case, while thepair
case is just a member field.
But that's about it.

- 449,505
- 63
- 781
- 982
-
9"It's a bit easier to get the data out of a pair than a tuple. A bit." I noticed. :P Although `.first` and `.second` are handy, they offer no help if a third (or more) member(s) are required in a code change. I've noticed I tend to use `std::get` regardless in any Getters that way I don't need to change everything, just the datatypes and any `make_pair` calls to `make_tuple` calls. – Casey Jul 14 '11 at 00:46
-
In what way is member access easier than a function call? – Yakk - Adam Nevraumont Jan 04 '16 at 15:21
-
5@Yakk: Um, I press "." and my IDE brings up a list of members. I didn't think people needed that spelled out. – Nicol Bolas Jan 04 '16 at 15:51
-
2I wonder if structured binding in c++17 already invalidates both 1 and 2 point of this answer? If so, please add a c++17 version of this too. – sandthorn Jan 28 '18 at 08:52
-
@sandthorn: How would structured binding make `tuple` standard layout? – Nicol Bolas Jan 28 '18 at 15:11
-
I would add that there's not much difference, two ways to do the same thing is really confusing. std::pair might be easier to constexpr-ify than std::tuple. IMO, modern code should use std::tuple unless constexpr is an issue. – Tanveer Badar Aug 12 '18 at 14:21
-
Being pedantic, a tuple of size one is generally standard-layout if the single member is, but bigger ones would currently need a specialization for the specific number of members to achieve that status as far as I can see, which just isn't worth the hassle. Anyway, I don't think those differences actually truly count. Having two different types is a big inconvenience though. – Deduplicator Nov 27 '19 at 00:45
An std::tuple
's name is longer (one extra character). More of those characters are typed with the right hand, so easier for most people to type.
That said, std::pair
can only have two values - not zero, one, three or more. TWO values. A tuple, however, has almost no semantic limitation on the number of values. An std::pair
, therefore, is a more accurate, type safe type to use if you actually want to specify a pair of values.

- 1,362
- 1
- 20
- 40

- 11,517
- 1
- 40
- 72
-
30LOL! Brilliant that you consider how it is typed! I would like to point out though that I probably type 'pair' more than 20% faster than 'tuple'. This is because my hands type each character alternatively, ie. RHS: p, LHS: a, RHS: i, LHS: r. At least for me I find that easier to do! - but you still get +1! – Richard Corden Jul 26 '11 at 18:38
-
21"*An std::pair, therefore, is a more accurate, type safe type to use if you actually want to specify a pair of values.*" It is not more type-safe or "accurate", it only (arguably) signals intent more directly. – ildjarn Aug 01 '12 at 00:28
-
@ildjam: Unless you consider *semantics*, that said, when I say "is a more accurate, type safe type...", I mean that not only is it more accurate, it is *also* type safe. – Arafangion Aug 01 '12 at 05:23
-
1@Arafangion : `std::tuple<>` is _also_ type-safe (how could it not be?), and `2` is no semantically different than `pair`. – ildjarn Aug 02 '12 at 03:59
-
@ildjarn: I never said that std::tuple<> wasn't typesafe. My assertion was that std::pair<> was *semantically* more accurate - perhaps I should have clarified that this was because a "pair" represents a "pair" of values, which, if that's what you mean, is better than saying "a tuple of two items..." – Arafangion Aug 02 '12 at 06:28
-
2"__An std::pair, therefore, is a more__ accurate, __type safe type to use__" And I think any English speaker will think of 'pair` and 'two' as completely synonymous. :-] – ildjarn Aug 02 '12 at 06:31
-
8@ildjam: We're splitting hairs here, but no, they aren't *completely* synonymous. When you say "two shoes", do you mean "Two shoes, which could well be both left shoes", or do you mean "A pair of shoes" (One of which is always left, and the other which is always right)? – Arafangion Aug 02 '12 at 06:42
This is a very late answer but note that, because std::pair
is defined with member variables, its size cannot be optimized using empty base class optimization (first
and second
must occupy distinct addresses, even if one or both is an empty class). This exacerbated by whatever alignment requirements second_type
has, so in the worst case the resulting std::pair
will be basically twice the size it needs to be.
std::tuple
only allows access through helper functions, so it's possible for it to derive from either type if one or the other is empty, saving on the overhead. GCC's implementation, at very least, definitely does this...you can poke through the headers to verify this but there's also this as evidence.

- 5,470
- 26
- 48
-
6Of course, [C++20 `[[no_unique_address]]`](https://en.cppreference.com/w/cpp/language/attributes/no_unique_address) should remove `std::pair`'s disadvantage. – Deduplicator Feb 08 '19 at 13:27
-
1"std::tuple only allows access through helper functions", or C++17 structured bindings. Sad that so many reasonable C++ answers are so quickly out of date these days. :-( – cosimo193 Oct 19 '20 at 15:16
-
Thinking about it, this answer is actually wrong. Consider a `T` which is empty and trivially copyable. That last one means that it's OK to `memcpy` from another existing `T`. This will copy a single byte, since the size of an empty type is 1. And if you have a `tuple
`, if you get a reference to the `T`, you can copy a byte over it. If `tuple` optimized `T`'s storage away, then it would undoubtedly overlap with `int`. So copying that byte over partially copies over the `int`, thus breaking it. – Nicol Bolas Dec 26 '21 at 16:10 -
This doesn't happen with base classes because there is an explicit carve out in the rules of when it is OK to do a `memcpy` to an object: it's not OK if the object is a base class subobject (note: this is extended to no_unique_address member subobjects in C++20). There is no such carve out for members of a `tuple`. – Nicol Bolas Dec 26 '21 at 16:11
Note that with C++ 17, one can use the same interface to read data from both pair and tuple with two elements.
auto [a, b] = FunctionToReturnPairOrTuple();
No need to use get<>
:)

- 424
- 4
- 6
-
this is awesome, yet does not detects references. Great for parametrized unit tests with std:touple – no one special Mar 06 '23 at 10:06
It is, perhaps, worth noting that cppreference states:
"A pair is a specific case of a std::tuple with two elements."

- 89
- 6
-
1Looking back through [`std::pair`'s change history](https://en.cppreference.com/mwiki/index.php?title=cpp%2Futility%2Fpair&diff=119614&oldid=4587) this text did not appear when the question was asked. The earliest the text appears in the history is [two years later](https://en.cppreference.com/mwiki/index.php?title=cpp%2Futility%2Fpair&diff=47522&oldid=4587) – Casey Apr 19 '21 at 22:18
For what it's worth, I find the GDB output of std::tuple to be far more difficult to read. Obviously if you need more than 2 values then std::pair won't work, but I do consider this a point in favor of structs.

- 3,111
- 26
- 37
-
That's why when I used them in classes I wrap the gross line `std::get<0>(tupleName)` in a getter; `GetX()` is a lot easier to read and shorter. It has a small disadvantage that if you forget to make it a `const` method someone can do something stupid like this: `GetX() = 20;`. – Casey Jul 26 '11 at 18:26