Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ std::equal -- rationale behind not testing for the 2 ranges having equal size?

Tags:

c++

stl

I just wrote some code to test the behavior of std::equal, and came away surprised:

int main()
{
  try
  {
    std::list<int> lst1;
    std::list<int> lst2;

    if(!std::equal(lst1.begin(), lst1.end(), lst2.begin()))
      throw std::logic_error("Error: 2 empty lists should always be equal");

    lst2.push_back(5);

    if(std::equal(lst1.begin(), lst1.end(), lst2.begin()))
      throw std::logic_error("Error: comparing 2 lists where one is not empty should not be equal");
  }
  catch(std::exception& e)
  {
    std::cerr << e.what();
  }  
}

The output (a surprise to me):

Error: comparing 2 lists where one is not empty should not be equal

Observation: why is it the std::equal does not first check if the 2 containers have the same size() ? Was there a legitimate reason?

like image 475
sivabudh Avatar asked Mar 16 '10 18:03

sivabudh


3 Answers

Observation: why is it the std::equal does not first check if the 2 containers have the same size() ? Was there a legitimate reason?

How? You do do not pass containers to the function, you pass in iterators. The function has no way of knowing the size of the second container. All it can do is assume bona fide that the user passed in two valid container ranges (i.e. that the second range is correctly specified as the half-open interval [lst2.begin(), lst2.begin() - lst1.begin() + lst1.end()[) and act accordingly.

like image 73
Konrad Rudolph Avatar answered Oct 12 '22 11:10

Konrad Rudolph


You can always write your own version of equal that does effectively what you want:

template <class InputIterator1, class InputIterator2>
bool equalx(InputIterator1 first1, InputIterator1 last1,
            InputIterator2 first2, InputIterator2 last2)
{
  while ((first1 != last1) && (first2 != last2))
  {
    if (*first1 != *first2)   // or: if (!pred(*first1,*first2)), for pred version
      return false;
    ++first1; ++first2;
  }
  return (first1 == last1) && (first2 == last2);
}

In order to make sure both ranges have the same number of elements, the signature must include an end to the second range.

like image 40
R Samuel Klatchko Avatar answered Oct 12 '22 12:10

R Samuel Klatchko


Because checking the size may be an O(n) operation.

like image 34
eduffy Avatar answered Oct 12 '22 13:10

eduffy