18

My impression is that it is always better to define my own struct, such that I can use meaningful field names instead of first and second.

One place where the standard uses std::pair is for accessing elements of std::map. first is the key, and second the value. Would not it be much better to have a specific key_value_pair template, and refer to its fields as key and value instead of first and second? It seems to me that it would make code considerably more readable at no cost.

Rémi
  • 3,705
  • 1
  • 28
  • 39
  • 3
    But there *is* a cost! More code. Repeated bugs all over the place. Slightly different design choices every time. If you just want to store two values, what is wrong with `std::pair`? If you have a type, with some meaning, and some member functions, that just happens to have two data members, fine, write your own `class`. But for a pair of objects, why not call it `pair`? – BoBTFish Oct 29 '13 at 10:33
  • 2
    I found this related question: http://stackoverflow.com/questions/2236182/what-is-the-difference-between-using-a-struct-with-two-fields-and-a-pair?lq=1 . That still is not enough motivation for me to use `std::pair`. But I guess that is a matter of personal taste. – Rémi Oct 29 '13 at 10:36
  • @Rémi: the question could be generalized to `std::tuple`. – Matthieu M. Oct 29 '13 at 10:42
  • 1
    Another similar question: http://stackoverflow.com/questions/3607352/struct-with-2-cells-vs-stdpair?rq=1 . Still I am not convinced by any of the answer that std::pair might be useful. – Rémi Oct 29 '13 at 10:42

1 Answers1

11

I generally use pairs (and tuples) when I need a local package of 2 or more objects.

The primary usecase is for the return type of a function: C++ does not allow returning multiple values, but allows returning a structure with multiple fields. Rather than use output parameters, I prefer using a pair or tuple.

The second usecase is for ad-hoc storage of elements; for example to automagically generate operator< for

struct A { int a; int b; int c; };

You can write operator< this way:

bool operator<(A const& left, A const& right) {
    return std::tie(left.a , left.b , left.c )
         < std::tie(right.a, right.b, right.c);
}

it automagically generates a correct lexicographical order (so many people screw up those operators...).

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • Thanks. It is not really related to my question, but I am glad to learn that `std::tie` exists. The ready-made `operator<` might be useful indeed. In situations where using `first` and `second` does not hurt readability, using a pair might be convenient. But I really hate using `first` and `second` for maps. – Rémi Oct 29 '13 at 11:07
  • This works for a host of boilerplate methods: adding `make_tie` methods reduces `=` `==` `<` and `swap` to a O(1) code, and isolates bugs in `make_tie` where they can be universal rather than hidden in a corner case. – Yakk - Adam Nevraumont Oct 29 '13 at 11:12
  • 1
    @Rémi: oh, I definitely agree with your point about `map`; here `.key` and `.value` would be much better! – Matthieu M. Oct 29 '13 at 12:00