Невозможно использовать stl-карту со структурой?
struct Node
{
int a;
int b;
};
Node node;
node.a = 2;
node.b = 3;
map<int, int> aa;
aa[1]=1; //O.K.
map<Node, int> bb;
bb[node]=1; //Compile Error
Когда я попытался отобразить структуру в int, это дало мне ошибку компиляции.
Зачем?
Спасибо!
Ответы
Ответ 1
Для того, чтобы быть полезной в качестве ключа на карте, вы должны иметь возможность сравнить ее с помощью operator<()
. Вам нужно добавить такой оператор в класс node:
struct Node
{
int a;
int b;
bool operator<( const Node & n ) const {
return this->a < n.a; // for example
}
};
Конечно, что действительный оператор действительно зависит от того, какое сравнение фактически означает для вашей структуры.
Ответ 2
Вы должны указать std:: map, как сравнить объекты Node. По умолчанию он пытается сделать это, используя меньше оператора. Но для Node вы не указали меньше оператора. Самое простое решение - предоставить его.
Пример бесплатной функции:
bool operator<(Node const& n1, Node const& n2)
{
return n1.a<n2.a || (n1.a==n2.a && n1.b<n2.b);
}
Заметим, что для любой пары объектов Node x, y с !(x<y)
и !(y<x)
карта будет считать x и y равными (тот же ключ).
Ответ 3
Вам нужно определить меньше оператора, чтобы включить сравнения для вашего типа Node:
struct Node
{
int a;
int b;
};
bool operator<(Node const& n1, Node const& n2)
{
// TODO: Specify condition as you need
return ... ;
}
Здесь вы можете проверить, что LessThan Comparable означает для пользовательского типа.
Альтернативное решение - определить функтор, основанный на std:: binary_function. С точки зрения дизайна эта опция имеет преимущества, потому что сравнение эффективно отделено от класса Node
. Это позволяет определять карты, специализированные с различными условиями сравнения (функторы).
#include <map>
struct Node
{
int a;
int b;
};
struct NodeLessThan
: public std::binary_function<Node, Node, bool>
{
bool operator() (Node const& n1, Node const& n2) const
{
// TODO: your condition
return n1.a < n2.a;
}
};
int main()
{
Node node;
node.a = 2;
node.b = 3;
typedef std::map<Node, int, NodeLessThan> node_map_t;
node_map_t bb;
bb[node] = 1;
}
Таким образом, вы можете определить больше сравнений, чем просто NodeLessThan
, например, используя разные условия или сравнивая только Node::a
другое сравнение обоих компонентов, Node::a
и Node::b
. Затем определяются различные типы карт:
typedef std::map<Node, int, NodeLessThan> node_map_t;
typedef std::map<Node, int, NodeLessThanByA> node_map_a_t;
Такая развязка менее навязчива (вообще не касается класса Node) и выгодна для достижения более расширяемого решения.
Ответ 4
Если вам действительно не нужно сортировать данные по ключу, вы можете использовать новый unordered_map:
#include <unordered_map>
...
std::tr1::unordered_map<Node, int> aa; // Doesn't require operator<(Node, Node)
Вам понадобится недавний компилятор для этого.
UPDATE
Как указывает Нил, вам нужна специализированная хеш-функция, если вы хотите использовать unordered_map с Node
.
struct NodeHash : std::unary_function<Node, size_t>
{
size_t operator()(Node const & node) const
{
return static_cast<size_t>(node.a + 1) * static_cast<size_t>(node.b + 1);
}
};
И тогда карта станет:
std::tr1::unordered_map<Node, int, NodeHash> aa;
Кроме того, как говорит sellibitze, для сравнения ключей в случае хэш-столкновения необходим оператор ==:
bool operator==(const Node & lhs, const Node & rhs)
{
return lhs.a == rhs.a && rhs.b == rhs.b;
}
Итак, я думаю, что std:: map намного проще использовать.
Ответ 5
Не могли бы вы отправить сообщение об ошибке компилятора. Они предназначены для того, чтобы сказать вам, что не так.
Я предполагаю, что ваша ошибка возникает, поскольку Node
не реализует оператор сравнения, который требуется для карты, чтобы идентифицировать его.