Russian Qt Forum

Программирование => С/C++ => Тема начата: Igors от Декабрь 18, 2014, 11:41



Название: оператор < для указателей
Отправлено: Igors от Декабрь 18, 2014, 11:41
Добрый день

Структура имеет оператор <, но в др контейнере (напр std::map) надо xранить не саму структуру, а указатель на нее. Приходится как-то так
Код
C++ (Qt)
struct MyPtr {
 MyPtr( MyStruct * ptr = 0 ) : MPtr(ptr) {}
 
 bool operator < ( const MyPtr & sec ) const
 {
   if (!mPtr) return sec.mPtr != 0;  // указатели могут быть NULL
   if (!sec.mPtr) return false;
 
   return *mPtr < *sec.mPtr;
 }
 
 MyStruct * mPtr;
};
Конечно можно перекрывать сравнения в контейнерах (хранящих указатели), но это не выгоднее. Нет ли удобного стандартного решения?

Спасибо


Название: Re: оператор < для указателей
Отправлено: Fregloin от Декабрь 18, 2014, 13:11
не совсем понятен вопрос...

покажите в коде где и что вы сравниваете, и как хотелось бы


Название: Re: оператор < для указателей
Отправлено: Igors от Декабрь 18, 2014, 13:39
не совсем понятен вопрос...

покажите в коде где и что вы сравниваете, и как хотелось бы
Пример
Код
C++ (Qt)
std::map <MyStruct *, int> theMap;
Так будут сравниваться указатели и для каждого MyStruct храниться свое значение int. А надо чтобы одно значение хранилось для всех одинаковых MyStruct


Название: Re: оператор < для указателей
Отправлено: Fregloin от Декабрь 19, 2014, 11:34
А что понимается под "одинаковыми" структурами? Их указатели или содержимое? Все равно не понимаю вопроса.
Скорее всего вы не совсем полностью описали что хотите получить или входные данные. Так как я читаю и в упор не вижу проблемы.


Название: Re: оператор < для указателей
Отправлено: Fregloin от Декабрь 19, 2014, 11:36
Так кажется я начал понимать. Вам нужно что бы ваши структуры выступали в качестве ключей в мапе и по ним шла сортировка? Я так понимаю?


Название: Re: оператор < для указателей
Отправлено: Пантер от Декабрь 19, 2014, 11:37
Так кажется я начал понимать. Вам нужно что бы ваши структуры выступали в качестве ключей в мапе и по ним шла сортировка? Я так понимаю?
Да, ты правильно понял. И чтобы сравнивались не указатели, а внутренние данные.


Название: Re: оператор < для указателей
Отправлено: Igors от Декабрь 19, 2014, 12:07
Так кажется я начал понимать. Вам нужно что бы ваши структуры выступали в качестве ключей в мапе и по ним шла сортировка? Я так понимаю?
Совершенно верно. Но сами структуры при этом хранятся в др месте и копированию не подлежат. Пример: удалить повторяющиеся эл-ты из контейнера не меняя при этом порядок оставшихся

А что понимается под "одинаковыми" структурами? Их указатели или содержимое?
Содержимое, как это определено оператором < для структуры


Название: Re: оператор < для указателей
Отправлено: m_ax от Декабрь 19, 2014, 12:34
Храните в мапе не указатели, а обёртки, для которых определяйте операторы:

Код
C++ (Qt)
template <class T>
class pointer_wrapper
{
public:
   pointer_wrapper(const T * p) : ptr(p) {}
 
   template <class R>
   friend bool operator<(const pointer_wrapper<R> &, const pointer_wrapper<R>&);
 
private:
   const T * ptr;
};
 
template <class R>
bool operator<(const pointer_wrapper<R> & x, const pointer_wrapper<R> & y)
{
   return *(x.ptr) < *(y.ptr);
}
 
 
std::map <pointer_wrapper<MyStruct> , int> theMap;
 

 


Название: Re: оператор < для указателей
Отправлено: Igors от Декабрь 19, 2014, 13:13
Главное - сунуть template, а там хоть трава не расти :'(  Как же мне достучаться до ptr? (хоть бы оператор -> перекрыли). С какой радости он const? И как помещать его в контейнер без конструктора по умолчанию? Имя pointer_wrapper лишено всякой определенности. А проверяться на NULL нам недосуг - надо ж бежать что-то еще "обобщать"

Да уж, "техника на грани фантастики" - простую идею оформить не можем. Но неужели такой простой вещи нет в бусте  ??? ??? Не верю, наверное плохо смотрели


Название: Re: оператор < для указателей
Отправлено: m_ax от Декабрь 19, 2014, 13:32
Цитировать
Как же мне достучаться до ptr?
ну если это вызывает такие сложности..

Цитировать
С какой радости он const?
Это просто пример, иллюстрирующий мысль.. const он или не const уже вам решать.. Я предположил, что если он используется в качестве ключа в мапе, то логичнее сделать указатель константным, в противном случае, если вы через ключ пытаетесь и данные его поменять, то это уже что-то нечто.. (хотя чему я удивляюсь..)

Цитировать
А проверяться на NULL нам недосуг - надо ж бежать что-то еще "обобщать"

Проверяйте, это не сложно..

Цитировать
И как помещать его в контейнер без конструктора по умолчанию?
А как вы ключ-значение в мап добавляете?

Код
C++ (Qt)
MyStruct * myStruct;
theMap[myStruct] = 1;
...
 
theMap[pointer_wrapper(myStruct)] = 1;
...
 
какие здесь могут проблемы возникнуть?





Название: Re: оператор < для указателей
Отправлено: Пантер от Декабрь 19, 2014, 13:52
Главное - сунуть template, а там хоть трава не расти :'(  Как же мне достучаться до ptr? (хоть бы оператор -> перекрыли). С какой радости он const? И как помещать его в контейнер без конструктора по умолчанию? Имя pointer_wrapper лишено всякой определенности. А проверяться на NULL нам недосуг - надо ж бежать что-то еще "обобщать"

Да уж, "техника на грани фантастики" - простую идею оформить не можем. Но неужели такой простой вещи нет в бусте  ??? ??? Не верю, наверное плохо смотрели
Тебе дали идею, а ты придираешься к реализации. Нафига человеку все реализовывать, чтобы показать саму идею?


Название: Re: оператор < для указателей
Отправлено: Igors от Декабрь 19, 2014, 14:21
А как вы ключ-значение в мап добавляете?
Код
C++ (Qt)
MyStruct * myStruct;
theMap[myStruct] = 1;
...
 
theMap[pointer_wrapper(myStruct)] = 1;
...
 
А зачем pointer_wrapper() если есть конструктор принимающий такой тип?

Тебе дали идею, а ты придираешься к реализации. Нафига человеку все реализовывать, чтобы показать саму идею?
Если хотели "дать идею" то можно было напр так
Цитировать
Не слышал про такое, но это легко сделать темплейтом
А если приводить код - так уж приводить, пусть неполный но без ляпов на каждом шагу.

Да, но ведь это "велосипед" - а я хочу стандартными средствами  :)


Название: Re: оператор < для указателей
Отправлено: __Heaven__ от Декабрь 19, 2014, 16:09
А вот интересно.
Что у нас будет с мэпом, когда мы возьмем и по неконстантному указателю модифицируем объект?
Загнется?


Название: Re: оператор < для указателей
Отправлено: Old от Декабрь 19, 2014, 16:43
А вот интересно.
Что у нас будет с мэпом, когда мы возьмем и по неконстантному указателю модифицируем объект?
Загнется?
Что считать "загнется"? :)
Может перестать находить значение по "новому" ключу.


Название: Re: оператор < для указателей
Отправлено: __Heaven__ от Декабрь 19, 2014, 16:49
Может перестать находить значение по "новому" ключу.
А на вставку и нахождение других значений никак не повлияет?


Название: Re: оператор < для указателей
Отправлено: Igors от Декабрь 19, 2014, 17:14
А на вставку и нахождение других значений никак не повлияет?
Необязательно загнется, но при вставках/удалениях начнет лупить как попало. Когда сортируем функтором/лямбдой (вместо оператора <) - имеем те же "шансы на успех"  :)

А константность здесь не к месту. напр
Код
C++ (Qt)
std::vector <CComparedPtr<MyStruct> > vec;
..
std::sort(vec.begin(), vec.end());
И теперь нельзя менять содержимое - придется const_cast


Название: Re: оператор < для указателей
Отправлено: Old от Декабрь 19, 2014, 19:12
А константность здесь не к месту. напр
...
И теперь нельзя менять содержимое - придется const_cast
Не придумывайте, константность здесь не помешает. Сортироваться будут враперы (которые не константные), а вовсе не константные указатели.
Код
C++ (Qt)
template <class T>
class pointer_wrapper
{
public:
pointer_wrapper( const T * p ) : ptr( p ) {}
 
const T operator*() const { return *ptr; }
 
template <class R>
friend bool operator<( const pointer_wrapper<R> &, const pointer_wrapper<R> & );
 
private:
const T * ptr;
};
 
template <class R>
bool operator<( const pointer_wrapper<R> &x, const pointer_wrapper<R> &y )
{
return *(x.ptr) < *(y.ptr);
}
 
typedef pointer_wrapper<int> Value;
 
int main( int argc, char *argv[] )
{
std::vector<Value> vec;
 
vec.push_back( Value( new int( 9 ) ) );
vec.push_back( Value( new int( 1 ) ) );
vec.push_back( Value( new int( 7 ) ) );
vec.push_back( Value( new int( 2 ) ) );
vec.push_back( Value( new int( 5 ) ) );
 
foreach( const Value &v, vec )
qDebug() << *v;
 
std::sort( vec.begin(), vec.end() );
 
foreach( const Value &v, vec )
qDebug() << *v;
 
return 0;
}
 


Название: Re: оператор < для указателей
Отправлено: Igors от Декабрь 20, 2014, 08:15
Сортироваться будут враперы (которые не константные), а вовсе не константные указатели.
Будут, но что потом делать с отсортированным?
Код
C++ (Qt)
const T operator*() const { return *ptr; }
 
Ой  :)


Название: Re: оператор < для указателей
Отправлено: Old от Декабрь 20, 2014, 09:02
Будут, но что потом делать с отсортированным?
Вы хотели получить из указателя ключ, предполагаю, что вы будете смотреть порядок этих ключей.