Invalid Operands to binary expression(const point and const point - c++

map<pair<int,int>,int>pairOfNumbers;
pairOfNumbers.insert(pair<pair<int,int>,int>({1,2},2));
this is working, but
map<pair<point,point>,int>PointsOnLine;
PointsOnLine.insert(pair<pair<point,point>,int>(make_pair(points[i],points[j]),count));
this doesn't.
point is just a structure of two ints x and y;
I keep getting the error 'Invalid Operands to binary expression(const point and const point' this is the structure of point.
struct point
{
int x;
int y;
public:
bool operator==(const point& p)
{
if(x==p.x && y==p.y)
return true;
else
return false;
}
bool operator!=(const point& p)
{
if(x==p.x &&y==p.y)
return false;
else
return true;
}
};
how do I insert two points and distance between them in the map?
in Xcode I get this error

Your point type does not support weak-ordering. It has no method of determining is-less-than. You may think you don't need that because your point is actually tucked into a std::pair<point,point> but you do.
std::pair<T1,T2> supports weak ordering only if T1 and T2 do. In your case, they're the same type, so for a std::pair<point,point> to be used as key in a std::map<std::pair<point,pint>,T>, point must support weak ordering.
To support weak ordering, you must either provide an operator< that compares two of your objects in question, or a comparator functor type that does the same thing. The easiest way for you to do this would be:
#include <tuple>
struct point
{
int x;
int y;
bool operator <(const point& p) const
{
return std::tie(x, y) < std::tie(p.x, p.y);
}
bool operator ==(const point& p) const
{
return !(*this < p || p < *this);
}
bool operator !=(const point& p) const
{
return *this < p || p < *this;
}
};
I took liberty to redefine operator == and operator != to utilize the weak order properties of the proper operator <. It wasn't necessary, but ultimately it's just easier if operators root to as basic code as possible. With the above change you should be able to use both point and std::pair<point,point> as key types in std::map and std::set. In truth, a strict weak ordering can define all of the basic comparators (<=, >, >=, !=, ==) as derivations from operator < in one form or another (or relative to something that does). I challenge you to consider them, try implementing them, and above all, writing some test harnesses that verify your implementation.

Related

C2678 when compiling. Visual Studio refers to xutility [duplicate]

This question already has answers here:
How to use std::find() with vector of custom class?
(2 answers)
Closed last year.
If I have a class
class Point
{
public:
Point() {}
Point(int _col, int _row) : row(_row), col(_col) {}
int row, col;
};
how can I use std::find() to check whether the point is already in vector? DO I have to overload operator== ?
I am trying to do this
#include <algorithm>
if(std::find(v.begin(), v.end(), x) != v.end()) {
/* v contains x */
} else {
/* v does not contain x */
}
Almost every answer I find on Stack Overflow suggest using find to check whether the object is in std::vector but none of them explains whether it compares the pointer of objects or the actual values of the object.
The C++ standard (draft N3242) says (in section 25.2.5 [alg.find]) that std::find:
Returns: The first iterator i in the range [first,last) for which the following corresponding conditions hold: *i == value[...]. Returns last if no such iterator is found.
Your question of whether it will search based on the value or the address of the object depends on how operator== is implemented. The simple answer is: std::find will return an iterator to the object for which operator== returned true.
Usually, this will just be a value-based comparison (because operator== is usually implemented to compare the values of two objects), and so you should generally expect std::find to search the range for the value you've provided (not the address of the object you provided).
It's possible for operator== to be implemented such that it compares based on address, like so:
bool operator==(const Point& left, const Point& right) {
return &left == &right;
}
Using this operator== will compare addresses, and so std::find will search for an object that has the same address as the one you've provided. It's generally a bad idea to implement operator== like this, though. Most people would implement operator== like so:
bool operator==(const Point& left, const Point& right) {
return left.row == right.row && left.col == right.col;
}
which, when used with std::find, will compare Points based on their values.
Unless your types are PODs fundamental types, you will need to provide an equality function, member or not.
There are two fundamental versions of std::find, one that assumes an equality operator and the other uses an equality function you supply.
I recommend that you add operator== and operator< to any class that will be compared for equality or ordered.
Here's an updated version of your class:
class Point
{
int x; // These are private by default.
int y;
public:
Point(int new_x, int new_y) : x(new_x), y(new_y)
{ ; }
bool operator==(const Point& p) const
{
return (x == p.x) && (y == p.y);
}
};
The member method operator== allows comparison without exposing the values to friends or the public.
If you want to use a free standing comparison function, you will need to either make the values public or make the function a friend:
class Point
{
int x; // These are private by default.
int y;
public:
Point(int new_x, int new_y) : x(new_x), y(new_y)
{ ; }
friend bool operator==(const Point& a, const Point& b);
};
bool operator==(const Point& a, const Point& b)
{
return (a.x == b.x) && (a.y == b.y);
}
If you want to use the free standing function with std::find, the example would be:
std::vector<Point> point_container;
//...
Point p;
std::vector<Point>::const_iterator iter;
iter = std::find(point_container.begin(), point_container.end(),
p,
Equal_Points);
Where Equal_Points is a free standing function that can compare the members of two Points.

std::find how does it work? operator== [duplicate]

This question already has answers here:
How to use std::find() with vector of custom class?
(2 answers)
Closed last year.
If I have a class
class Point
{
public:
Point() {}
Point(int _col, int _row) : row(_row), col(_col) {}
int row, col;
};
how can I use std::find() to check whether the point is already in vector? DO I have to overload operator== ?
I am trying to do this
#include <algorithm>
if(std::find(v.begin(), v.end(), x) != v.end()) {
/* v contains x */
} else {
/* v does not contain x */
}
Almost every answer I find on Stack Overflow suggest using find to check whether the object is in std::vector but none of them explains whether it compares the pointer of objects or the actual values of the object.
The C++ standard (draft N3242) says (in section 25.2.5 [alg.find]) that std::find:
Returns: The first iterator i in the range [first,last) for which the following corresponding conditions hold: *i == value[...]. Returns last if no such iterator is found.
Your question of whether it will search based on the value or the address of the object depends on how operator== is implemented. The simple answer is: std::find will return an iterator to the object for which operator== returned true.
Usually, this will just be a value-based comparison (because operator== is usually implemented to compare the values of two objects), and so you should generally expect std::find to search the range for the value you've provided (not the address of the object you provided).
It's possible for operator== to be implemented such that it compares based on address, like so:
bool operator==(const Point& left, const Point& right) {
return &left == &right;
}
Using this operator== will compare addresses, and so std::find will search for an object that has the same address as the one you've provided. It's generally a bad idea to implement operator== like this, though. Most people would implement operator== like so:
bool operator==(const Point& left, const Point& right) {
return left.row == right.row && left.col == right.col;
}
which, when used with std::find, will compare Points based on their values.
Unless your types are PODs fundamental types, you will need to provide an equality function, member or not.
There are two fundamental versions of std::find, one that assumes an equality operator and the other uses an equality function you supply.
I recommend that you add operator== and operator< to any class that will be compared for equality or ordered.
Here's an updated version of your class:
class Point
{
int x; // These are private by default.
int y;
public:
Point(int new_x, int new_y) : x(new_x), y(new_y)
{ ; }
bool operator==(const Point& p) const
{
return (x == p.x) && (y == p.y);
}
};
The member method operator== allows comparison without exposing the values to friends or the public.
If you want to use a free standing comparison function, you will need to either make the values public or make the function a friend:
class Point
{
int x; // These are private by default.
int y;
public:
Point(int new_x, int new_y) : x(new_x), y(new_y)
{ ; }
friend bool operator==(const Point& a, const Point& b);
};
bool operator==(const Point& a, const Point& b)
{
return (a.x == b.x) && (a.y == b.y);
}
If you want to use the free standing function with std::find, the example would be:
std::vector<Point> point_container;
//...
Point p;
std::vector<Point>::const_iterator iter;
iter = std::find(point_container.begin(), point_container.end(),
p,
Equal_Points);
Where Equal_Points is a free standing function that can compare the members of two Points.

Find equal instance in a c++ set

I'm using a c++ STL set and I want to know if it's present in the set an equivalent instance. To retrive the instance I'm using the find set method. The problem is that it doesn't work. I think the problem is in my comparator object:
bool SetComparator::operator ()( const Point* i1, const Point* i2 ) const {
if ( *i1 == *i2 )
return false;
return true;
}
The operator == is redefined for the class Point in a simple way:
bool Point::operator ==( const Point& p ) const {
if (x == p.x && y == p.y)
return true;
return false;
}
After a debugging I can see that the find method calls operator() but it doesn't find the same instance so the find returns end() but I know that there is an equal object. I think the problem is related to the set internal order. How can I do?
std::set uses partial ordering (i.e. the operator<), so when you pass in an operator that can only decide equality, you break the assumption of the implementation of std::set. Your SetComparator has to behave similar to std::less.
For example std::pair (utility) implements relational operators for two items, e.g. for operator<:
template <class T1, class T2>
bool operator< (const std::pair<T1,T2>& lhs, const std::pair<T1,T2>& rhs) {
return lhs.first<rhs.first || (!(rhs.first<lhs.first) && lhs.second<rhs.second);
}
note that (!(rhs.first<lhs.first) && lhs.second<rhs.second) is a workaround for (rhs.first == lhs.first && lhs.second < rhs.second) using only operator<
If you only want to check for equality maybe using std::set is the wrong decision. If you can hash your objects, you could use a std::unordered_set (C++11 and later).

Check if structure is not in vector

I have a vector of structs. I need to check if the struct is or is not in the vector. The entire struct, not any specific member. It throws me this error upon compile time:
binary '==' : no operator found which takes a left-hand operand of type 'NavigationNode'
(or there is no acceptable conversion)
My struct:
struct NavigationNode{
int x, y; //their x and y position on the grid
float f, g, h;
int parentGCost;
int value;
};
NavigationNode currentNode;
The vector
vector<NavigationNode> openList;
My find:
if (find(closedList.begin(), closedList.end(), currentNode) == closedList.end() )
{
}
You need to overload operator==.
As global function:
bool operator==( const NavigationNode& lhs, const NavigationNode& rhs )
{
// compare lhs and rhs
}
Or as member function:
bool operator==( const NavigationNode& other ) const
{
// compare this & other
}
You will have to write an equality operator for your custom type. Assuming all variables have to be the same for two NavigationNode objects to be the same, it should look something like this:
bool floatEqual(float a, float b)
{
// adapt this comparison to fit your use-case - see the notes below
static const int EPSILON = 0.00001; // arbitrarily chosen - needs to be adapted to the occuring values!
return std::abs(a – b) <= EPSILON;
}
bool operator==(NavigationNode const & a, NavigationNode const & b)
{
return a.x == b.x &&
a.y == b.y &&
floatEqual(a.f, b.f) &&
floatEqual(a.g, b.g) &&
floatEqual(a.h, b.h) &&
a.parentGCost == b.parentGCost &&
a.value == b.value;
}
Even if you could also do it as a member function of NavigationNode, the recommended way is to implement the operator== as a free function (that way, both parameters can take advantage of any possible implicit conversions).
Note on float comparison: Due to how floating point numbers are represented, it is not a trivial task to compare them. Just checking for equality might not give the desired results. See e.g. this question for details:
What is the most effective way for float and double comparison?
You need to overload the comparison operator.
If your intention of "==" is "are each of the values contained in my struct equal to the corresponding members in this other struct" then you can write that.
bool operator==(const NavigationNode& lhs, const NavigationNode& rhs)
{
return /* compare each member in here */
}

How should I compare pairs of pointers (for sort predicate)

I have a STL container full of billions of the following objects
pair<SomeClass*, SomeClass*>
I need some function of the following form
/*returns items sorted biggest first */
bool sortPredicate (pair<SomeClass*, SomeClass*>two, pair<SomeClass*, SomeClass*> one)
{
return ???;
}
Is there some trick I can use to very quickly compare pairs of pointers?
Edit 1: A clarification
In the end I just want to sort the list of pointer-pairs such that all of the duplicates are next to each other. Assume that there is no clear method in SomeClass that can be used for this purpose---I only have pointer pairs, and I want to find all identical pairs (in parallel). I thought a sort would do the trick, but if you can think of a better parallel method, let me know.
Edit 2: A clarification
Fixed my code (the arguments to the sort predicate were wrong--they should be pairs).
It is a quirk of C++ that arbitrary pointers of the same type are not (necessarily) comparable with <, but are comparable with std::less.
Unfortunately, the operator< for std::pair is defined in terms of operator< on the components, not std::less.
So, assuming that you want two pairs to fall in the same sort position if and only if they point to the same two objects, you need:
// "less than"
template<typename T>
bool lt(const T &lhs, const T &rhs) {
return std::less<T>()(lhs, rhs);
}
typedef std::pair<SomeClass*, SomeClass*> mypair;
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lt(lhs.first, rhs.first)
|| (!lt(rhs.first, lhs.first) && lt(lhs.second, rhs.second));
}
On pretty much any system you can name, this should compile to the same code as return lhs < rhs;, but that is not formally correct. If the referands of the pointers are all subobjects of the same object (for instance if you have a huge array and all the pairs point to elements of that one array), then operator< is OK for the pointers and hence OK for std::pair<pointer,pointer>.
If you want to pairs to fall in the same sort position if and only if the objects they point to sort the same, then you'd add the extra dereference:
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lt(*lhs.first, *rhs.first)
|| (!lt(*rhs.first, *lhs.first) && lt(*lhs.second, *rhs.second));
}
and perhaps you'd also add checks for null pointers, if those are permitted. Of course if you know that SomeClass really is a class type, not a pointer type, then you don't need to use std::less in the version above, just define operator< for SomeClass and:
inline bool lessptr(const SomeClass *lhs, const SomeClass *rhs) {
if (lhs == 0) return rhs != 0;
if (rhs == 0) return false;
return *lhs < *rhs;
}
bool sortPredicate(const mypair &lhs, const mypair &rhs) {
return lessptr(lhs.first, rhs.first)
|| (!lessptr(rhs.first, lhs.first) && lessptr(lhs.second, rhs.second));
}
You may or may not be able to optimise that a bit, since there are some repeated null checks performed in both the first and second calls to lessptr. If you care that much, see what the compiler does with it.
Assuming your class has comparison operators:
bool sortPredicate (SomeClass *two, SomeClass *one)
{
return *two > *one;
}
If you just want to compare the pointer addresses, use std::greater<T>:
sort(container.begin(), container.end(), std::greater<SomeClass *>());
EDIT: OK, I really have no idea what you are trying to do now, with your most recent edit. Why not just use the default sort, if all you want to do is find duplicates?
If I understand correctly Your predicate should have the following signature
bool sortPredicate(pair<SomeClass*, SomeClass*>& lhs, pair<SomeClass*, SomeClass*>& rhs);
I know nothing about Your class and if there is any natural order for it, so it's hard to guess how You want to sort it. In The comment You write that the biggest items should be first. I assume there is < operator for the class. How about this?
bool sortPredicate(pair<SomeClass*, SomeClass*>& lhs, pair<SomeClass*, SomeClass*>& rhs)
{
if(!(*(lhs.first) < *(rhs.first) || *(rhs.first) < *(lhs.first))) // If there is == operator use it.
{
return *(rhs.second) < *(lhs.second);
}
else
{
return *(rhs.first) < *(lhs.first);
}
}
EDIT: Ok thx for clarifying. How about this?
bool sortPredicate(pair<SomeClass*, SomeClass*>& lhs, pair<SomeClass*, SomeClass*>& rhs)
{
if(lhs.first == rhs.first)
{
return rhs.second < lhs.second;
}
else
{
return rhs.first < lhs.first;
}
}
You should define an operator<on your pair class. I assume that your pair holds item1 and item2. So:
template <class T>
class pair{
private:
T item1;
T item2
public:
// [...] other stuff goes here
// here the comparing
bool operator<(pair p){
return (item1 < p.item1 || (item1 == p.item1 && item2 < p.item2));
}
};
This solution assumes that the items have defined the < and the == operators.
I suppose I didn't meet what you were exactly looking for, but I recommend to overload the <, >, and == operators in your pair class.