tags:

views:

89

answers:

5

Possible Duplicate:
What is the difference between using a struct with two fields and a pair?

Dear all,

I have a little question about pairs and struct. Is there any advantage to use a std::pair instead of a struct with two cells ? I have used pairs for a while but the main problem is readability : If you want to represent for example a duple (int "label",double "value") you can use either a :

typedef std::pair<int,double> myElem;

or a

typedef struct {
    int label;
    double value;
} myElem;

The code becomes more readable if your statements have a "semantic" sense (you will always know what x.label is. that's not the case with x.first).

However, I guess there is an advantage using pair. Is it more performant or something else ?

Thanks for your answer.

+2  A: 

However, I guess there is an advantage using pair. Is it more performant or something else?

I doubt it, an instantiated std::pair is just a struct, after all. std::pair comes with operator< defined, though. But that shouldn't be too hard to do yourself for a struct with only two members.

So I usually do as you reasoned: a struct with dedicated member names is easier to read than first and second.

sbi
+2  A: 

A pair is implemented as a templated struct. It provides you with a shorthand for creating a (typically heterogenous) pair. Also, there are some constraints on the types that you can use with a pair:

Type requirements

T1 and T2 must both be models of Assignable. Additional operations have additional requirements. Pair's default constructor may only be used if both T1 and T2 are DefaultConstructible, operator== may only be used if both T1 and T2 are EqualityComparable, and operator< may only be used if both T1 and T2 are LessThanComparable.

(from SGI STL std::pair documentation)

Defining your own POD may make sense if the types do not follow any of these constraints or if you do not care about them.

Finally, I guess it is a matter of personal choice/coding style.

dirkgently
+1  A: 

With a std::pair, you are free to use functors from the STL such as select1st or select2nd. Likewise it allows you to use other generic functions with your pair, such as operator< and others. Admittedly, with the advent of boost/tr1, you could achieve much the same effect by using bind.

Your point about readability is very true though.

Brian O'Kennedy
+2  A: 

Its primary advantage is that it's generic. For example, when you retrieve something from an std::map, you get the key and the associated value as the first and second items in an std::pair.

Likewise, when you use std::equal_range to find a set of equal values in a collection, you get iterators to the beginning and end of the range as the first and second items in an std::pair.

It's hard to imagine meaningful labels that would apply to both of these, so they settled for a couple that don't mean very much, but at least aren't misleading. Using 'key' and 'data' would work for std::map, but be misleading for std::equal_range (and if you switched to something like lower_bound and upper_bound to make them more meaningful for std::equal_range, it'd be equally wrong for items in std::map).

Jerry Coffin
Just my opinion, but I don't like the choice they made. a map-entry should have been (key,value) and a range should have been (begin, end). Now, we are stuck with having to use the meaningless and misleading (first, second) in both cases. And it is difficult and not-idiomic to change the field-names.
stefaanv
+2  A: 

In terms of performance: it's unlikely to change anything, you're just sugar coating it.

In terms of usability, I would rather use a custom struct, which can be declared this way (by the way):

struct MyElement
{
  int label;
  double value;
};

I am a strong proponent of strong typing, and I much prefer a "real" structure (and better yet, class) than an ad-hoc tuple whenever it's more than a fleeting thing.

Mainly because:

  • As you noted first and second don't carry much meaning
  • You cannot add methods / other fields to a std::pair
  • You cannot add class invariants to a std::pair

All in all, I really think that maintenance benefits from using a custom dedicated structure that a one-size-fits-them-all tuple.

Matthieu M.