C++ STL wrong keys types
can't understand this: g++ compiler is angry on:
lengths.insert(pair<Deux,long>(d,one));
where
struct Deux {long big; long small};
map<Deux, long> lengths;
Deux d;
long one;
so, g++ said, that i miss operator<
. after making overloaded operator<
for struct Deux
, i saw new interesting, but the same error:
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;
also used structure Node:
struct Node {
long nam开发者_JAVA技巧e;
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;
}*/
and error is:
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*> >]()
The compiler complains that there is no operator <
for Deux
(I guess). The key must be a comparable class with operator <
or you must pass a third template parameter to map - the comparator.
You see, the map keeps its keys in an ordered way. In order to order them, it needs a predicate. By default it tries to use operator <
try writing something like this:
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;
}
You did not mention the error message. Always post it!
So, I need to fork my post into two distinct sections.
Missing Declaration.
`error: 'Deux' was not declared in this scope`
That's because Deux
is unknown at the point where you declare the map<>
.
You need to declare Deux
before map<Deux, long>
, because map<Deux, long>
requires the full definition of its parameters.
Missing Comparator.
`error: no match for 'operator<' in '__x < __y'`
That's because you haven't defined operator<
for Deux
.`
If you can define a logical operator<
, i.e. one that is not arbitrarily chosen for sorting purposes, you could do it like this:
// must be in same namespace as Deux
bool operator< (Deux const &lhs, Deux const &rhs) {
return lhs.foo < rhs.foo;
}
If it needs access to non-public members, you can make it a member function:
bool operator< (Deux const &rhs) {
return this->foo < rhs.foo;
}
If such comparison would be arbitrary, do as Constantinius suggests.
Next time
You could have saved us time by posting your actual code or a minimal testcase, as well as by mentioning the error message.
My guess is that your struct is missing a compare
function, to make an internal sorting of your Deux
objects as keys. In a map, they have to be sorted.
This is the definition of std::map
template < class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key,T> > > class map;
So if you define a function like this:
bool compare_deux(Deux& a, Deux& b) {
return a.big < b.big;
}
and pass it as a template argument:
map <Deux, long, compare_deux> lengths;
you should be fine.
Use make_pair.
lengths.insert(make_pair<Deux,long>(d,one));
Just to add yet another reply, here's how I would implement Deux
to be strictly ordered. We just use lexicographic ordering:
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!
Alternatively, we could have spared ourselves the pain and said:
typedef std::pair<long, long> Deux;
std::map<Deux, T> m; // always works, lexicographic compare is provided by default
Always best not to reinvent the wheel!
Post a comment if you also want pair hashing using hash_combine
to use unordered containers.
You need to declare the < operator or pass a comparison function on map creation.
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;
}
};
精彩评论