Как использовать структуру в std :: map? - PullRequest
4 голосов
/ 29 октября 2010

У меня есть сложная структура, которую я хочу поместить в качестве ключа std :: map для быстрого создания списка всех уникальных объектов:

union somecomplexstruct {
     struct {
        more_structs val1, val2;
        even_more_structs val3, val4;
        lots_of_more_structs val5;
     };
     unsigned int DATA[3];
};

typedef map<somecomplexstruct, int, greater<somecomplexstruct> > somecomplexstructMap;

Но он говорит об ошибке: error C2784: 'bool std::operator >(const std::vector<_Ty,_Alloc> &,const std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const std::vector<_Ty,_Alloc> &' from 'const somecomplexstruct'

Как мне заставить мою структуру работать там?

Редактировать: Все заработало, спасибо всем!Вот код:

inline bool operator>(const somecomplexstruct &v1, const somecomplexstruct &v2){
    if(v1.DATA[0] > v2.DATA[0]) return 1;
    if(v1.DATA[0] < v2.DATA[0]) return 0;
    if(v1.DATA[1] > v2.DATA[1]) return 1;
    if(v1.DATA[1] < v2.DATA[1]) return 0;
    return v1.DATA[2] > v2.DATA[2];
}

Ответы [ 4 ]

9 голосов
/ 29 октября 2010

std::greater<> вызывает operator>() для своей работы, поэтому вам нужно перегрузить его, если вы хотите использовать std::greater<>.

Это должно выглядеть так:

inline bool operator>(const somecomplexstruct& lhs, const somecomplexstruct& rhs)
{
  // implement your ordering here. 
}
3 голосов
/ 29 октября 2010

С вашей функцией operator> подумайте, что произойдет, если вы сравните {1, 0, 0} и {0, 1, 0}. Если вы сравниваете a > b, он возвращает true из первого сравнения. Если вы сравниваете b > a, это возвращает true из второго сравнения. Так что это не дает рефлексивного свойства для сравнения, скремблирования карты. Чтобы карта работала правильно, вы должны определить свой оператор> так, чтобы a > b == !(b > a) для всех возможных неравных пар значений, которые можно сравнивать.

редактировать

Самый простой / лучший способ убедиться, что ваш оператор правильно рефлексивен, - это обеспечить для каждого теста, который может возвращать true, у вас также есть тест с тем же условием, и операнды меняются местами, которые возвращают false. Так что, если у вас есть

if(v1.DATA[1] > v2.DATA[1]) return 1;

в вашей функции вам нужно

if(v2.DATA[1] > v1.DATA[1]) return 0;

или эквивалент где-нибудь.

2 голосов
/ 29 октября 2010

Вот лексикографический компаратор для сложной структуры

struct D {
  struct A {
    bool operator <(const A &) const;
  } a;
  struct B {
    bool operator <(const B &) const;
  } b;
  struct C {
    bool operator <(const C &) const;
  } c;
  template <class T> ne(const T & a, const T & b) {
    if (a < b) return true;
    if (b < a) return true;
    return false;
  }
  bool operator < (const D & that) const {
    if (ne(a, that.a)) return a < that.a;
    if (ne(b, that.b)) return b < that.b;
    return c < that.c;
  }
};
0 голосов
/ 30 октября 2010

Если ваша карта содержит только указатели на вашу структуру, вам не нужно делать всю эту сложную перегрузку операторов.

Поэтому ваш typedef выглядит так:

typedef map<somecomplexstruct*, int, greater<somecomplexstruct*> > somecomplexstructMap;

Структуры обычно имеют только открытые элементы данных и не требуют перегрузки операторов.

Это означает, что вы должны быть осторожны с тем, когда и как вы освобождаете память для указателей. У каждого подхода есть свои плюсы и минусы, как и у всего.

...