Why does vector comparison with < operator compare each item twice?

  • A+
Category:Languages

In this example comparing two vectors with < operator results in operator <, defined on the Integer class, being called twice for each element. However, this doesn't happen when comparing two vectors with == operator.

#include<iostream> #include<vector>  class Integer {     public:         Integer(int value) : m_value(value) {}         friend bool operator<(const Integer& lhs, const Integer& rhs);         friend bool operator==(const Integer& lhs, const Integer& rhs);      private:         int m_value;  };  bool operator<(const Integer& lhs, const Integer& rhs) {             std::cout << lhs.m_value << " < " << rhs.m_value << '/n';             return lhs.m_value < rhs.m_value; } bool operator==(const Integer& lhs, const Integer& rhs) {             std::cout << lhs.m_value << " == " << rhs.m_value << '/n';             return lhs.m_value == rhs.m_value; }   int main() {     std::vector<Integer> ivec1 {1,2,3};     std::vector<Integer> ivec2 {1,2,3};     std::cout << (ivec1 < ivec2) << '/n';     std::cout << (ivec1 == ivec2) << std::endl;     return 0; } 

This code prints:

1 < 1 1 < 1 2 < 2 2 < 2 3 < 3 3 < 3 0 1 == 1 2 == 2 3 == 3 1 

Why is that so?

 


If a < b returns false, it doesn't tell you whether b < a, and you have to test that. That's because the element-by-element ordering of std::vector can have three outcomes for one pair of elements a, b:

  • a < b, the vector comparison returns true.
  • b < a, the vector comparison returns false.
  • Neither of the above, the next pair of elements must be tested.

So it has to compare both directions. You could see this more clearly by adding identification data to your class:

#include<iostream> #include<vector>  class Integer {     public:         Integer(int value, char tag) : m_value(value), m_tag(tag) {}         friend bool operator<(const Integer& lhs, const Integer& rhs);         friend bool operator==(const Integer& lhs, const Integer& rhs);      private:         int m_value;         char m_tag;  };  bool operator<(const Integer& lhs, const Integer& rhs) {             std::cout << lhs.m_value << ' ' << lhs.m_tag << " < " << rhs.m_value << ' ' << rhs.m_tag << '/n';             return lhs.m_value < rhs.m_value; } bool operator==(const Integer& lhs, const Integer& rhs) {             std::cout << lhs.m_value << ' ' << lhs.m_tag << " == " << rhs.m_value << ' ' << rhs.m_tag << '/n';             return lhs.m_value == rhs.m_value; }   int main() {     std::vector<Integer> ivec1 {{1, 'a'} ,{2, 'a'}, {3, 'a'}};     std::vector<Integer> ivec2 {{1, 'b'} ,{2, 'b'}, {3, 'b'}};     std::cout << (ivec1 < ivec2) << '/n';     std::cout << (ivec1 == ivec2) << std::endl;     return 0; } 

This produces:

1 a < 1 b     1 b < 1 a     2 a < 2 b     2 b < 2 a     3 a < 3 b     3 b < 3 a     0     1 a == 1 b     2 a == 2 b     3 a == 3 b     1 

[Live example]

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: