Сравнение vector<shared_ptr>
От: Alexander Pazdnikov  
Дата: 29.12.11 10:45
Оценка:
Здравствуйте, Коллеги.

Помогите, пожалуйста, перегрузить оператор сравнения для std::vector<boost::shared_ptr> чтобы сравнивались не указатели, а объекты по этим указателям.

#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <iostream>

using namespace std;
using namespace boost;

int main()
{
    vector<shared_ptr<int> > v1, v2;

    v1.push_back(make_shared<int>(1));
    v2.push_back(make_shared<int>(1));

    bool equal = v1 == v2; // здесь хочу получить true вместо false

    cout << equal << endl;
    
    cout << "v1[0] = " << v1[0] << " -> " << *v1[0] << endl;
    cout << "v2[0] = " << v2[0] << " -> " << *v2[0] << endl;

    vector<int> v3, v4;

    v3.push_back(1);
    v4.push_back(1);
    
    equal = v3 == v4;

    cout << equal << endl;
    
    cout << "v3[0] = " << v3[0] << endl;
    cout << "v4[0] = " << v4[0] << endl;

    return 0;
}
vector shared_ptr equal сранение
Re: Сравнение vector<shared_ptr>
От: Сыроежка  
Дата: 29.12.11 11:11
Оценка:
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP> Здравствуйте, Коллеги.


AP>Помогите, пожалуйста, перегрузить оператор сравнения для std::vector<boost::shared_ptr> чтобы сравнивались не указатели, а объекты по этим указателям.


AP>
AP>#include <vector>
AP>#include <boost/shared_ptr.hpp>
AP>#include <boost/make_shared.hpp>
AP>#include <iostream>

AP>using namespace std;
AP>using namespace boost;

AP>int main()
AP>{
AP>    vector<shared_ptr<int> > v1, v2;

AP>    v1.push_back(make_shared<int>(1));
AP>    v2.push_back(make_shared<int>(1));

AP>    bool equal = v1 == v2; // здесь хочу получить true вместо false

AP>    cout << equal << endl;
    
AP>    cout << "v1[0] = " << v1[0] << " -> " << *v1[0] << endl;
AP>    cout << "v2[0] = " << v2[0] << " -> " << *v2[0] << endl;

AP>    vector<int> v3, v4;

AP>    v3.push_back(1);
AP>    v4.push_back(1);
    
AP>    equal = v3 == v4;

AP>    cout << equal << endl;
    
AP>    cout << "v3[0] = " << v3[0] << endl;
AP>    cout << "v4[0] = " << v4[0] << endl;

AP>    return 0;
AP>}
AP>


Вы можете воспользоваться стандартным алгоритмом std::lexicographical_compare с предикатом.
Меня можно встретить на www.cpp.forum24.ru
Re[2]: Сравнение vector<shared_ptr>
От: Alexey F  
Дата: 29.12.11 11:29
Оценка: +2
Здравствуйте, Сыроежка, Вы писали:

AP>>
...
AP>>    bool equal = v1 == v2; // здесь хочу получить true вместо false
...
AP>>

С>Вы можете воспользоваться стандартным алгоритмом std::lexicographical_compare с предикатом.
Эмм...

std::lexicographical_compare

Lexicographical less-than comparison
Returns true if range [first1,last1) compares lexicographically less than the range [first2,last2).

Если и говорить про алгоритмы, то нужен std::equal со своим предикатом, но только с проверкой длины векторов:
bool equal = v1.size() == v2.size() && std::equal( v1.begin(), v1.end(), v2.begin(), predicate );

Не думаю, что топик-стартеру понравится.
Re[3]: Сравнение vector<shared_ptr>
От: Сыроежка  
Дата: 29.12.11 11:38
Оценка: -1
Здравствуйте, Alexey F, Вы писали:

AF>Здравствуйте, Сыроежка, Вы писали:


AP>>>
AF>...
AP>>>    bool equal = v1 == v2; // здесь хочу получить true вместо false
AF>...
AP>>>

С>>Вы можете воспользоваться стандартным алгоритмом std::lexicographical_compare с предикатом.
AF>Эмм...
AF>

AF>std::lexicographical_compare

AF>Lexicographical less-than comparison
AF>Returns true if range [first1,last1) compares lexicographically less than the range [first2,last2).

AF>Если и говорить про алгоритмы, то нужен std::equal со своим предикатом, но только с проверкой длины векторов:
AF>
AF>bool equal = v1.size() == v2.size() && std::equal( v1.begin(), v1.end(), v2.begin(), predicate );
AF>

AF>Не думаю, что топик-стартеру понравится.

Совершенно не понял, почему вы вместо std::lexicographical_compare предлагаете использлвать std::equal, когда последний не сравнивает размеры диапазонов?! Или это вы так стараетесь себе жизнь усложнить?! std::lexicographical_compare вполне подходит для выяснения равны между собой две последовательности или нет.
Меня можно встретить на www.cpp.forum24.ru
Re[4]: Сравнение vector<shared_ptr>
От: Alexey F  
Дата: 29.12.11 11:48
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Совершенно не понял, почему вы вместо 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 с пользовательским предикатом стал бы возвращать минимальный элемент
Re[3]: Сравнение vector<shared_ptr>
От: uzhas Ниоткуда  
Дата: 29.12.11 11:56
Оценка:
Здравствуйте, Alexey F, Вы писали:

AF>Не думаю, что топик-стартеру понравится.

ваш вариант в бою: http://ideone.com/EWZDO
Re: Сравнение vector<shared_ptr>
От: night beast СССР  
Дата: 29.12.11 12:00
Оценка: +2
Здравствуйте, Alexander Pazdnikov, Вы писали:

AP> Здравствуйте, Коллеги.


AP>Помогите, пожалуйста, перегрузить оператор сравнения для std::vector<boost::shared_ptr> чтобы сравнивались не указатели, а объекты по этим указателям.


своя обертка над shared_ptr не подходит?
Re[4]: Сравнение vector<shared_ptr>
От: uzhas Ниоткуда  
Дата: 29.12.11 12:02
Оценка: 3 (2)
Здравствуйте, uzhas, Вы писали:

U>ваш вариант в бою:

что-то в компараторе накосячил
дубль2: http://ideone.com/SGpw7
Re[5]: Сравнение vector<shared_ptr>
От: Сыроежка  
Дата: 29.12.11 12:02
Оценка: -1
Здравствуйте, 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 с пользовательским предикатом стал бы возвращать минимальный элемент

А причем здесь этот оператор? Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.
Меня можно встретить на www.cpp.forum24.ru
Re[4]: Сравнение vector<shared_ptr>
От: Alexey F  
Дата: 29.12.11 12:06
Оценка:
Здравствуйте, Сыроежка, Вы писали:

Да более того (сразу не посмотрел). lexicographical_compare возвратит true на первых же равных элементах, т.е. предикаты вида { return a == b } не напишешь:
for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2) {
    if (cmp(*first1, *first2)) return true;
    if (cmp(*first2, *first1)) return false;
}
return first1 == last1 && first2 != last2;
Re[6]: Сравнение vector<shared_ptr>
От: Alexey F  
Дата: 29.12.11 12:19
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.

Для lexicographical_compare придётся писать предикат сложнее a == b:
здесь
Автор: Alexey F
Дата: 29.12.11

(код взят из стандарта, только < заменён на cmp) и даже не a != b с отрицанием результата — это ещё больше (помимо вводящего в заблуждение имени) затуманит цель кода для того, кто будет потом в нём разбираться.
Re[7]: Сравнение vector<shared_ptr>
От: Сыроежка  
Дата: 29.12.11 12:31
Оценка: :)
Здравствуйте, Alexey F, Вы писали:

AF>Здравствуйте, Сыроежка, Вы писали:


С>>Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.

AF>Для lexicographical_compare придётся писать предикат сложнее a == b:
AF>здесь
Автор: Alexey F
Дата: 29.12.11

AF>(код взят из стандарта, только < заменён на cmp) и даже не a != b с отрицанием результата — это ещё больше (помимо вводящего в заблуждение имени) затуманит цель кода для того, кто будет потом в нём разбираться.

На самом деле предикат простой и не затуманит. Другое дело, что внутри алгоритма этот предикат вызывается дважды, что, как говорится, не комильфо. А так написать предикат очень просто. Достаточно завести внутри класса логической переменную, при каждом вызове предиката которая будет менть значение на прлтивоположное. При первом вызове предиката сотреть, если эта переменная равна false, то возвращать ее. При втором вызове возвращать условие a != b

То есть оператор функции будет состоять из одной строчки

return ( ( first = !first ) && ( a != b ) );

При этом начальное значение first должно быть равно true
Меня можно встретить на www.cpp.forum24.ru
Re[8]: Сравнение vector<shared_ptr>
От: uzhas Ниоткуда  
Дата: 29.12.11 12:35
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Достаточно завести внутри класса логической переменную, при каждом вызове предиката которая будет менть значение на прлтивоположное. При первом вызове предиката сотреть, если эта переменная равна false, то возвращать ее. При втором вызове возвращать условие a != b

бросай курить, вставай на лыжи!
Re[4]: Сравнение vector<shared_ptr>
От: Centaur Россия  
Дата: 29.12.11 12:42
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>std::lexicographical_compare вполне подходит для выяснения равны между собой две последовательности или нет.


Не подходит. Лексикографическое сравнение в лучшем случае даст эквивалентность (!(a<b) && !(b<a)), а не равенство (a==b). И нет, эти отношения не обязаны быть согласованы для конкретного типа—аргумента шаблона.

Поэтому таки std::equal, с предварительным сравнением размеров и с кастомным предикатом вида [](x,y) { return *x == *y; }.
Re[5]: Сравнение vector<shared_ptr>
От: Сыроежка  
Дата: 29.12.11 12:49
Оценка: -1
Здравствуйте, Alexey F, Вы писали:

AF>Здравствуйте, Сыроежка, Вы писали:


AF>Да более того (сразу не посмотрел). lexicographical_compare возвратит true на первых же равных элементах, т.е. предикаты вида { return a == b } не напишешь:

AF>
AF>for ( ; first1 != last1 && first2 != last2 ; ++first1, ++first2) {
AF>    if (cmp(*first1, *first2)) return true;
AF>    if (cmp(*first2, *first1)) return false;
AF>}
AF>return first1 == last1 && first2 != last2;
AF>



Я вам уже ответил в другом месте. Но повторю здесь свой ответ.

На самом деле предикат простой и не затуманит. Другое дело, что внутри алгоритма этот предикат вызывается дважды, что, как говорится, не комильфо. А так написать предикат очень просто. Достаточно завести внутри класса логической переменную, при каждом вызове предиката которая будет менть значение на прлтивоположное. При первом вызове предиката смотреть, если эта переменная равна false, то возвращать ее. При втором вызове возвращать условие a != b

То есть оператор функции будет состоять из одной строчки

return ( ( first = !first ) && ( a != b ) );

При этом начальное значение first должно быть равно true
Меня можно встретить на www.cpp.forum24.ru
Re[6]: Сравнение vector<shared_ptr>
От: Centaur Россия  
Дата: 29.12.11 13:35
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.


Так нельзя делать, потому что предикат должен индуцировать отношение строгого слабого порядка.
Re[5]: Сравнение vector<shared_ptr>
От: Кодт Россия  
Дата: 29.12.11 13:50
Оценка:
Здравствуйте, 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;
}
Перекуём баги на фичи!
Re[6]: Сравнение vector<shared_ptr>
От: Кодт Россия  
Дата: 29.12.11 13:55
Оценка:
Здравствуйте, Сыроежка, Вы писали:

С>А причем здесь этот оператор? Вы же используете алгоритм с предикатом. Можно исхитриться и придумать предикат, который будет давать нужный результат. Например, предикат, который будет возращать значение оператора != при каждом нечетном вызове предиката.


Stateful функция плоха тем, что вызывающая сторона должна специфицировать порядок её вызова.

Вот, например, для for_each этот порядок определён, а для всяких операций сравнения — нет.
Этим пользуются дебажные версии библиотек, проверяя, соответствует ли аргумент-предикат требуемой аксиоматике, а если данные должны быть упорядочены — то заодно, упорядочены ли они на самом деле?

Так что этот фокус с чётностью прокатит только для одной конкретной версии STL, притом, что работать он будет в режиме undefined behavior (которое в частном случае является искомым и желанным поведением...)
Перекуём баги на фичи!
Re[6]: Сравнение vector<shared_ptr>
От: Centaur Россия  
Дата: 29.12.11 16:19
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Ну, если над типом введены два НЕЗАВИСИМЫХ отношения — равенство (==) и порядок (<), тогда конечно.

К>Но обычно, всё-таки, если определено <, то все остальные отношения следуют ему: a>b = b<a, a<=b = !(b>a), a!=b = (a<b)||(b<a) и т.д.

Не уверен, что это справедливо хотя бы даже для юникодной строки. Ну и вообще любые типы с существенно частичным порядком.
Re[7]: Сравнение vector<shared_ptr>
От: Кодт Россия  
Дата: 29.12.11 17:05
Оценка:
Здравствуйте, Centaur, Вы писали:

C>Не уверен, что это справедливо хотя бы даже для юникодной строки. Ну и вообще любые типы с существенно частичным порядком.


Ну если юникодную строку нарочно сравнивать не через strcmp (wcscmp), а через strcoll, — то конечно.
Это как раз ситуация, когда отношения равенства и порядка будут введены произвольно и без оглядки друг на друга. ССЗБ.

Часто (не знаю, как в жизни, а на форумах точно) люди вводят оператор < над своим типом от балды, просто потому, что это требование какого-нибудь контейнера (std::map) или алгоритма (std::sort). Естественно, что в лучшем случае они заботятся об аксиоматике порядка (и то не всегда, а иногда — да вот прямо здесь! — заботятся о том, чтобы её безболезненно сломать). А об согласовании с другими операторами даже не вспоминают.

Кстати, в бусте есть заготовка, порождающая наборы всяких разных операторов
http://www.boost.org/doc/libs/1_48_0/libs/utility/operators.htm
Перекуём баги на фичи!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.