C ++ STL неправильные типы ключей - PullRequest
1 голос
/ 06 июля 2011

не может этого понять: компилятор g ++ недоволен:

lengths.insert(pair<Deux,long>(d,one));

где

struct Deux {long big; long small};
map<Deux, long> lengths;
Deux d;
long one;

так что, g ++ сказал, что я скучаю по operator<.после перегрузки operator< для struct Deux я увидел новую интересную, но такую ​​же ошибку:

map <long, Node*>ArrayOfNodes;
map <long, Node*>::iterator it;  
  for (it=ArrayOfNodes[Root]->nodes.begin();it<ArrayOfNodes[Root]->nodes.end();++it)
      cout<<it->first<<endl;

также использовал узел структуры:

struct Node {
   long name;
   long guest;
   map <long,Node*>nodes;
/*bool operator<(const Node& node)const{
 if ((*this).name<node.name) return true;
 if ((*this).name>node.name) return false;
  return (*this).guest<(*this).guest;
}*/

и ошибка:

    no match for operator< in it < ((Path*)this)->Path::ArrayOfNodes.
 std::map<_Key, _Tp, _Compare, _Alloc>::operator[] [with _Key = long int, _Tp = Node*,
 _Compare = std::less<long int>, _Alloc = std::allocator<std::pair<const long int, Node*> >]
 (((const long int&)((const long int*)(&((Path*)this)->Path::Root))))->Node::nodes.std::map<_Key, _Tp, _Compare, _Alloc>::end 
 [with _Key = long int, _Tp = Node*, _Compare = std::less<long int>, _Alloc = std::allocator<std::pair<const long int, Node*> >]()

Ответы [ 6 ]

6 голосов
/ 06 июля 2011

Компилятор жалуется, что нет operator < для Deux (наверное). Ключ должен быть сопоставимого класса с operator <, или вы должны передать третий параметр шаблона для сопоставления - компаратор.

Видите ли, карта хранит свои ключи в упорядоченном виде. Для того, чтобы их заказать, нужен предикат. По умолчанию он пытается использовать operator <

попробуйте написать что-то вроде этого:

bool operator < (Deux const & d1, Deux const & d2)
{
   if(d1.big > d2.big)
      return false;
   if(d1.big < d2.big)
     return true;
   return d1.small < d2.small;  
}
3 голосов
/ 06 июля 2011

Вы не упомянули сообщение об ошибке.Всегда публиковать его!

Итак, мне нужно разбить свой пост на два отдельных раздела.

Отсутствует декларация.

`error: 'Deux' was not declared in this scope`

Это потому, что Deux неизвестно вточка, в которой вы объявляете map<>.

. Вам нужно объявить Deux до map<Deux, long>, потому что map<Deux, long> требует полного определения его параметров.

Отсутствует компаратор.

`error: no match for 'operator<' in '__x < __y'` 

Это потому, что вы не определили operator< для Deux .`

Если вы можете определить логический operator<, то есть тот, который не являетсяпроизвольно выбранный для сортировки, вы можете сделать это следующим образом:

// must be in same namespace as Deux
bool operator< (Deux const &lhs, Deux const &rhs) {
    return lhs.foo < rhs.foo;
}

Если ему нужен доступ к закрытым членам, вы можете сделать его функцией-членом:

bool operator< (Deux const &rhs) {
    return this->foo < rhs.foo;
}

Еслитакое сравнение было бы произвольным, как говорит Константиний.

В следующий раз

Вы могли бы сэкономить нам время, разместив свой действительный код или минимальный тестовый сценарий, а также упомянув сообщение об ошибке.

2 голосов
/ 06 июля 2011

Я предполагаю, что в вашей структуре отсутствует функция compare для внутренней сортировки ваших Deux объектов в качестве ключей.На карте они должны быть отсортированы.

Это определение std::map

template < class Key, class T, class Compare = less<Key>,
           class Allocator = allocator<pair<const Key,T> > > class map;

Так что если вы определяете функцию, подобную этой:

bool compare_deux(Deux& a, Deux& b) {
    return a.big < b.big;
}

и передайте его в качестве аргумента шаблона:

map <Deux, long, compare_deux> lengths;

все будет в порядке.

0 голосов
/ 06 июля 2011

Вам необходимо объявить оператор <или передать функцию сравнения при создании карты. </p>

struct Deux     
{
  long big; 
  long small

  bool operator < (const Deux &n) const
  {         
    if(big != n.big)
       return big < n.big;
    else
       return small < n.small;
   }
};
0 голосов
/ 06 июля 2011

Просто чтобы добавить еще один ответ, вот как я бы реализовал Deux, чтобы быть строго упорядоченным.Мы просто используем лексикографический порядок:

struct Deux
{
  long big, small;

  inline bool operator<(const Deux & o) const
  {
    return big < o.big || (!(o.big < big) && small < o.small);
  }
};

std::map<Deux, T> m; // works now!

В качестве альтернативы мы могли бы избавить себя от боли и сказать:

typedef std::pair<long, long> Deux;
std::map<Deux, T> m; // always works, lexicographic compare is provided by default

Всегда лучше не изобретать велосипед!

Оставьте комментарий, если вы также хотите, чтобы парное хэширование с использованием hash_combine использовало неупорядоченные контейнеры.

0 голосов
/ 06 июля 2011

Использование make_pair .

lengths.insert(make_pair<Deux,long>(d,one));
...