It seems impossible to create an std::map with a coordinate as key. When (x+y+z) is the same for both coordinates, the map just overrides the previous one. Example:
map[Coordinate(1, 0, 0)] = object1;
map[Coordinate(0, 1, 0)] = object2;
map[Coordinate(0, 0, 1)] = object3;
This will result in there being a std::map with 1 element, which contains object3
as value and Coordinate(0, 0, 1)
as key. How can I prevent this so it'll contain all values?
#pragma once
struct Coordinate {
double x, y, z;
Coordinate(double x, double y, double z) : x(x), y(y), z(z) {}
bool operator<(const Coordinate& coord) const {
if(x + y + z < coord.x + coord.y + coord.z)
return true;
return false;
}
bool operator==(const Coordinate& coord) const {
if(x == coord.x && y == coord.y && z == coord.z)
return true;
return false;
}
inline bool isInRange(Coordinate coord, int range) const {
if(pow(coord.x - this->x, 2) + pow(coord.y - this->y, 2) + pow(coord.z - this->z, 2) <= range*range)
return true;
return false;
}
};
« std::map is a sorted associative container that contains key-value pairs with unique keys. Keys are sorted by using the comparison function Compare. » from cppreference
The default comparison function is std::less
which will use the operator< on the Key
objects.
Thus, the problem lies in the operator<
of Coordinate
:
bool operator<(const Coordinate& coord) const {
if(x + y + z < coord.x + coord.y + coord.z)
return true;
return false;
}
(1, 0, 0) < (0, 1, 0)
is false but (0, 1, 0) < (1, 0, 0)
is also false, so as far as std::map
is concerned, (1, 0, 0) == (0, 1, 0)
.
In order to use Coordinate
objects as keys in a std::map
, you'll need to find the correct strict weak ordering criterion (the operator<
) that meets your needs.
As other said, you could use something like std::tie
(in C++11) which will first compare x
, then y
then z
like this :
bool operator<(const Coordinate& coord) const {
if(x < coord.x) return true;
if(x > coord.x) return false;
//x == coord.x
if(y < coord.y) return true;
if(y > coord.y) return false;
//x == coord.x && y == coord.y
if(z < coord.z) return true;
if(z > coord.z) return false;
//*this == coord
return false;
}
Your operator < must work so that all possible coordinates can be placed in a stable order. If you add the values then there are several combinations of coordinate that are indistinguishable from each other.
Try this
friend bool operator < (const Coordinate& left, const Coordinate& right)
{
if (left.z < right.z)
{
return true;
}
else if (right.z < left.z)
{
return false;
}
else if (left.y < right.y)
{
return true;
}
else if (right.y < left.y)
{
return false;
}
else if (left.x < right.x)
{
return true;
}
else /* (right.x < left.x) */
{
return false;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With