C++ std:: equal - обоснование не тестирования для 2 диапазонов, имеющих одинаковый размер?
Я просто написал код, чтобы проверить поведение std:: equal, и ушел удивленный:
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();
}
}
выход (сюрприз для меня):
Error: comparing 2 lists where one is not empty should not be equal
наблюдение: почему это std:: equal сначала не проверяет, имеют ли 2 контейнера одно и то же size()
? Была ли на то законная причина?
5 ответов
замечание: почему std:: equal не проверяет, имеют ли 2 контейнера одинаковый размер() ? Была ли на то законная причина?
как? Вы не передаете контейнеры функции, вы передаете в итераторы. Функция не имеет никакого способа узнать размер второго контейнера. Все, что он может сделать, это предположить, что пользователь прошел в двух допустимых диапазонах контейнеров (т. е. что второй диапазон правильно указан как полуоткрытый интервал [lst2.begin()
, lst2.begin()
- lst1.begin()
+ lst1.end()
[) и действовать соответственно.
вы всегда можете написать свою собственную версию equal, которая эффективно делает то, что вы хотите:
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);
}
чтобы убедиться, что оба диапазона имеют одинаковое количество элементов, подпись должна включать конец второго диапазона.
Он дает вам правильный ответ-вы сказали ему проверить, равны ли два контейнера в диапазоне lst1.begin()
до lst1.end()
. Вы все еще сравниваете два пустых списка, насколько это. Если вы измените код для сравнения с lst2.begin()
to lst2.end()
, вы получите то, что вы ожидали.
в C++14 добавили четыре аргумента перегрузки как в ответ Р Самуэль Klatchko по. И, по крайней мере, две реализации STL, которые я проверил (libc++ и MSVC), реализуют очевидную оптимизацию проверки расстояния для итераторов произвольного доступа.