Здравствуйте, Alexander Pazdnikov, Вы писали:
AP> Здравствуйте, Коллеги.
AP>Помогите, пожалуйста, перегрузить оператор сравнения для std::vector<boost::shared_ptr> чтобы сравнивались не указатели, а объекты по этим указателям.
AP>
Совершенно не понял, почему вы вместо std::lexicographical_compare предлагаете использлвать std::equal, когда последний не сравнивает размеры диапазонов?! Или это вы так стараетесь себе жизнь усложнить?! std::lexicographical_compare вполне подходит для выяснения равны между собой две последовательности или нет.
Здравствуйте, Сыроежка, Вы писали:
С>Совершенно не понял, почему вы вместо std::lexicographical_compare предлагаете использлвать std::equal, когда последний не сравнивает размеры диапазонов?! Или это вы так стараетесь себе жизнь усложнить?! std::lexicographical_compare вполне подходит для выяснения равны между собой две последовательности или нет.
Из-за его стандартной семантики — процитированное:
Returns true if range [first1,last1) compares lexicographically less than the range [first2,last2).
Лично я бы удивился, если бы, к примеру, operator< вдруг стал использоваться для проверки на равенство, а std::max_element с пользовательским предикатом стал бы возвращать минимальный элемент
Здравствуйте, Alexander Pazdnikov, Вы писали:
AP> Здравствуйте, Коллеги.
AP>Помогите, пожалуйста, перегрузить оператор сравнения для std::vector<boost::shared_ptr> чтобы сравнивались не указатели, а объекты по этим указателям.
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, Сыроежка, Вы писали:
С>>Совершенно не понял, почему вы вместо std::lexicographical_compare предлагаете использлвать std::equal, когда последний не сравнивает размеры диапазонов?! Или это вы так стараетесь себе жизнь усложнить?! std::lexicographical_compare вполне подходит для выяснения равны между собой две последовательности или нет. AF>Из-за его стандартной семантики — процитированное: AF>
AF>Returns true if range [first1,last1) compares lexicographically less than the range [first2,last2).
AF>Лично я бы удивился, если бы, к примеру, operator< вдруг стал использоваться для проверки на равенство, а std::max_element с пользовательским предикатом стал бы возвращать минимальный элемент
А причем здесь этот оператор? Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.
Да более того (сразу не посмотрел). lexicographical_compare возвратит true на первых же равных элементах, т.е. предикаты вида { return a == b } не напишешь:
Здравствуйте, Сыроежка, Вы писали:
С>Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.
Для lexicographical_compare придётся писать предикат сложнее a == b: здесь
(код взят из стандарта, только < заменён на cmp) и даже не a != b с отрицанием результата — это ещё больше (помимо вводящего в заблуждение имени) затуманит цель кода для того, кто будет потом в нём разбираться.
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, Сыроежка, Вы писали:
С>>Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката. AF>Для lexicographical_compare придётся писать предикат сложнее a == b: AF>здесь
AF>(код взят из стандарта, только < заменён на cmp) и даже не a != b с отрицанием результата — это ещё больше (помимо вводящего в заблуждение имени) затуманит цель кода для того, кто будет потом в нём разбираться.
На самом деле предикат простой и не затуманит. Другое дело, что внутри алгоритма этот предикат вызывается дважды, что, как говорится, не комильфо. А так написать предикат очень просто. Достаточно завести внутри класса логической переменную, при каждом вызове предиката которая будет менть значение на прлтивоположное. При первом вызове предиката сотреть, если эта переменная равна false, то возвращать ее. При втором вызове возвращать условие a != b
То есть оператор функции будет состоять из одной строчки
return ( ( first = !first ) && ( a != b ) );
При этом начальное значение first должно быть равно true
Здравствуйте, Сыроежка, Вы писали:
С>Достаточно завести внутри класса логической переменную, при каждом вызове предиката которая будет менть значение на прлтивоположное. При первом вызове предиката сотреть, если эта переменная равна false, то возвращать ее. При втором вызове возвращать условие a != b
бросай курить, вставай на лыжи!
Здравствуйте, Сыроежка, Вы писали:
С>std::lexicographical_compare вполне подходит для выяснения равны между собой две последовательности или нет.
Не подходит. Лексикографическое сравнение в лучшем случае даст эквивалентность (!(a<b) && !(b<a)), а не равенство (a==b). И нет, эти отношения не обязаны быть согласованы для конкретного типа—аргумента шаблона.
Поэтому таки std::equal, с предварительным сравнением размеров и с кастомным предикатом вида [](x,y) { return *x == *y; }.
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, Сыроежка, Вы писали:
AF>Да более того (сразу не посмотрел). lexicographical_compare возвратит true на первых же равных элементах, т.е. предикаты вида { return a == b } не напишешь: AF>
Я вам уже ответил в другом месте. Но повторю здесь свой ответ.
На самом деле предикат простой и не затуманит. Другое дело, что внутри алгоритма этот предикат вызывается дважды, что, как говорится, не комильфо. А так написать предикат очень просто. Достаточно завести внутри класса логической переменную, при каждом вызове предиката которая будет менть значение на прлтивоположное. При первом вызове предиката смотреть, если эта переменная равна false, то возвращать ее. При втором вызове возвращать условие a != b
То есть оператор функции будет состоять из одной строчки
return ( ( first = !first ) && ( a != b ) );
При этом начальное значение first должно быть равно true
Здравствуйте, Сыроежка, Вы писали:
С>Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.
Так нельзя делать, потому что предикат должен индуцировать отношение строгого слабого порядка.
Здравствуйте, Centaur, Вы писали:
C>Не подходит. Лексикографическое сравнение в лучшем случае даст эквивалентность (!(a<b) && !(b<a)), а не равенство (a==b). И нет, эти отношения не обязаны быть согласованы для конкретного типа—аргумента шаблона.
Ну, если над типом введены два НЕЗАВИСИМЫХ отношения — равенство (==) и порядок (<), тогда конечно.
Но обычно, всё-таки, если определено <, то все остальные отношения следуют ему: a>b = b<a, a<=b = !(b>a), a!=b = (a<b)||(b<a) и т.д.
Другое дело, что над типом может отсутствовать отношение порядка, а только равенство.
Вот тогда без std::equal или его рукодельных аналогов деваться некуда
template<class I, class J>
bool equal_ranges(I i, I ie, J j, J je)
{
while(i!=ie && j!=je && *i==*j) { ++i; ++j; }
return i==ie && j==je;
}
template<class I, class J, class E>
bool equal_ranges(I i, I ie, J j, J je, E eq)
{
while(i!=ie && j!=je && eq(*i,*j)) { ++i; ++j; }
return i==ie && j==je;
}
Здравствуйте, Сыроежка, Вы писали:
С>А причем здесь этот оператор? Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.
Stateful функция плоха тем, что вызывающая сторона должна специфицировать порядок её вызова.
Вот, например, для for_each этот порядок определён, а для всяких операций сравнения — нет.
Этим пользуются дебажные версии библиотек, проверяя, соответствует ли аргумент-предикат требуемой аксиоматике, а если данные должны быть упорядочены — то заодно, упорядочены ли они на самом деле?
Так что этот фокус с чётностью прокатит только для одной конкретной версии STL, притом, что работать он будет в режиме undefined behavior (которое в частном случае является искомым и желанным поведением...)
Здравствуйте, Кодт, Вы писали:
К>Ну, если над типом введены два НЕЗАВИСИМЫХ отношения — равенство (==) и порядок (<), тогда конечно. К>Но обычно, всё-таки, если определено <, то все остальные отношения следуют ему: a>b = b<a, a<=b = !(b>a), a!=b = (a<b)||(b<a) и т.д.
Не уверен, что это справедливо хотя бы даже для юникодной строки. Ну и вообще любые типы с существенно частичным порядком.
Здравствуйте, Centaur, Вы писали:
C>Не уверен, что это справедливо хотя бы даже для юникодной строки. Ну и вообще любые типы с существенно частичным порядком.
Ну если юникодную строку нарочно сравнивать не через strcmp (wcscmp), а через strcoll, — то конечно.
Это как раз ситуация, когда отношения равенства и порядка будут введены произвольно и без оглядки друг на друга. ССЗБ.
Часто (не знаю, как в жизни, а на форумах точно) люди вводят оператор < над своим типом от балды, просто потому, что это требование какого-нибудь контейнера (std::map) или алгоритма (std::sort). Естественно, что в лучшем случае они заботятся об аксиоматике порядка (и то не всегда, а иногда — да вот прямо здесь! — заботятся о том, чтобы её безболезненно сломать). А об согласовании с другими операторами даже не вспоминают.