I'm trying to use a simple structure as a map key:
class Foo{
.
.
.
struct index{
int x;
int y;
int z;
};
bool operator<(const index a, const index b);
.
.
.
}
And the function itslef:
bool Foo::operator<(const index a, const index b){
bool out = True;
if (a.x == b.x){
if (a.y == b.y){
if (a.z >= b.z) out = false;
}
else if(a.y > b.y) out = false;
} else if (a.x > b.x) out = false;
return out;
}
However, when I compile I get an error:
memMC.h:35: error: 'bool Foo::operator<(Foo::index,
Foo::index)' must take exactly one argument
As I understand this, the compilers wants to compare index to this Foo. How can I overload the operator then?
If you want to compare two indexes, move the overload inside the index structure:
struct index{
int x;
int y;
int z;
bool operator<(const index& a) const;
};
If you want to compare a Foo and an index (I doubt that, but I'll just put this here just in case), remove the second parameter, as it's not needed:
class Foo{
//...
bool operator<(const index& a) const;
};
Note that you should pass the index parameter by reference, to prevent unnecesarry copying.
EDIT: As Als correctly pointed out, this operator should be const.
< is binary infix comparison operator i.e it takes two arguments to compare to each other, So ideally it should be implemented as a free function, However if you implement it as a member function then it will take only one argument.
It shall compare the argument passed as parameter to the object on which the member function is being called.
Your member comparison operator should be like:
class Foo
{
//...
bool operator<(const index& rhs) const
{
/* comparison with *this */
}
//...
};
Related
Having code
struct node
{
node(int X , int Y):X(X),Y(Y){};
int X;
int Y;
friend bool operator ==(const node &X, const node &Y);
};
int main()
{
node one(5,5);
node two(5,5);
if ( one == two )
{
cout << " true " << endl;
}
return 0;
}
If i declare operator == as
bool node::operator ==(const node &X, constnode &Y)
{
return (X.X == X.Y && Y.X == Y.Y);
}
it requires one argument , however when i declare it as
bool operator ==(const node &X, constnode &Y)
{
return (X.X == X.Y && Y.X == Y.Y);
}
It requires two. I know defined by language , first definition requires one argument becouse the second is *this.
And the second definition its outside definition of operator == ( global ) which is not bound to any structure thu it does not pass *this in it.
But it is still defined as "friend" this basicly states ( by first definition ) that member function is friend function of its own class. How is this possible? Why does this compile?
A method declared as friend is practically not a method of the class, but a global function outside of the class, in the same namespace as the class.
So the following inline definition ...
struct node
{
node(int X , int Y):X(X),Y(Y){};
int X;
int Y;
friend bool operator ==(const node &lhs, const node &rhs) {
return (lhs.X == rhs.X && lhs.Y == rhs.Y);
}
};
... is the same as ...
bool operator ==(const node &lhs, const node &rhs)
{
return (lhs.X == rhs.X && lhs.Y == rhs.Y);
}
This is why your first definition of operator== is not a valid definition for the method declared as friend.
If you define the global operator== outside of the class, you actually only need the friend declaration if the global function requires access to private members of the class. In your case this is not required, because X and Y are public.
This is because first definition makes the operator== member function of node. Thus it can access this pointer so first pointer is implicitly this and you can carry on with one argument.
Second definition makes operator== friend function of node. Now friend function accesses members of a class by taking their references as it has no access to this pointer. Thus we need to specify the two parameters expolicitly.
Hope it helps
I am trying to find a simple example program that overloads the following operators of a mathematic vector.
Constructor // create
= (equals) // assign
+; -; +=; -= // add sub
*; /; *=; /= // multi divide
++; -- // plus minus
== // compare
>; >=
<; <=
[] // access a value
Cant seem to find any good simple tutorials. I emphasize the simple because I am only learning this stuff now. If someone could link me or even better program a simple overload for just one of the operators as an example would be incredible!
There are a few things to know when you write operators, which are not as often used with other functions.
The assign operators, for example, will return *this because you change the value of the vector:
class v {
public:
double x_, y_;
v& operator += (const v& rhs)
{
_x += rhs._x;
_y += rhs._y;
return *this;
}
};
Another interesting one, the pre ++ and post ++ are different only because of an unused parameter:
class v {
public:
double x_, y_;
v& operator ++ (); // ++v
v& operator ++ (int); // v++
};
The "equal" (assignment) is another one that is tricky when you use pointers. For a vector, it generally won't be a problem, but if you define a vector V and assign it to itself, you have to be careful:
class v {
public:
double x_, y_;
v& operator = (const v& rhs)
{
if(this != &rhs)
{
x_ = rhs.x_;
y_ = rhs.y_;
}
return *this;
}
};
In your case, the if() will most certainly not be useful, but think about doing something like this:
delete p_;
p_ = new foo;
p_->x_ = rhs.p_->x_;
If &rhs == this, then the delete p_ deleted the rhs pointer! That means accessing it on the 3rd line is a bug.
The rest should be easy enough to work with. The compare operators return bool and are const:
class v {
public:
double x_, y_;
bool operator == (const v& rhs) const
{
return x_ == rhs.x_ && y_ == rhs.y_;
}
};
Although, since C++20, you are expected to only declare the three way comparison operator <=> which allows the compiler to implement all the other comparison operators for you. This one returns a negative number (smaller: a < b), 0 (equal: a == b), or a positive number (larger: a > b).
I'm not sure what makes a vector bigger or smaller, I used the length from (0, 0) in this example:
class v {
public:
double x_, y_;
int operator <=> (const v& rhs) const
{
if(x_ == rhs.x_ && y_ == rhs.y_)
{
return 0;
}
return length() > rhs.length() ? 1 : -1;
}
};
Except for the [] operator. There are two versions of that one:
class v {
public:
// I would imagine you'd use an array but as a simple example...
double x_, y_;
double operator [] (int idx) const
{
return idx == 0 ? x_ : y_;
}
v_ref operator [] (int idx)
{
v_ref v(this, idx);
return v;
}
};
As you can see, the non-constant version of the [] operator returns a reference. This is necessary so you can write something like:
r[3] = 7.3;
r[3] returns that reference, then the assignment of the reference is called with 7.3 as the parameter. (Note that we should probably throw an error if you use 3 as the index when you only have 2 values: 0 and 1--this is not shown here)
class v_ref
{
public:
v *p_;
int i_;
v_ref(v *p, int i)
: p_(p), i_(i)
{
}
operator = (double q)
{
// again, I suppose you'd use an array instead!
if(i_ == 0)
{
p_->x_ = q;
}
else
{
p_->y_ = q;
}
}
};
Assuming you want some security, the vector pointer could make use of a reference counter so you know whether a main vector object gets deleted before all of its reference objects...
Another note: I would imagine that your constructor will allocate an array of double (or use an std::vector<double> type...) If you use new, remember to delete in the destructor and that's when the if() in the assignment operator is very important.
Suppose we have class name Default that have two attribute x and y.
The default operation to compare object is using attribute x.
When we would like to compare this object using other attribute y,
1. Is it safe to create new derive class that can compare by using attribute y and then casting pointer from Default to that new class and compare object?
2. What is alternative way to do this without decreasing the performance of operation?
The requirement is we can not change the the signature of sorting algorithm to pass on function pointer to difference comparator.
By the way this method is required no cost for convert or copy data.
class Default {public:int x; int y;};
class Compare1 : public Default {};
bool operator < (const Default &left,const Default &right)
{
return left.x < right.x;
}
bool operator < (const Compare1 &left,const Compare1 &right)
{
return left.y < right.y;
}
template<typename T>
int *sort_element(const T *data, int size)
{
int *permute;
//... do some sorting by using < comparator ...
return permute;
}
int main(){
Default *obj;
int obj_size;
//… initialize obj and obj size..
// sorting object with default order.
int *output_default = sort_element(obj, obj_size)
// sorting with customize comparator.
Compare1 *custom1 = static_cast<Compare1*>(obj);
int *output_custom1 = sort_element(custom1, obj_size);
}
Better is passing a functor or lambda as compare function when you're sorting them. Your sort function must accept a function:
template<typename T, typename F>
int *sort_element(const T *data, int size, F comp)
{
....
if (comp(a, b))
....
...
}
Then
// Sort by x
sort_element(..., [](const Default &a, const Default &b) {
return a.x < b.x;
});
// Sort by y
sort_element(..., [](const Default &a, const Default &b) {
return a.y < b.y;
});
If you haven't C++11 you can use function object (functor) instead:
struct fx
{
bool operator()(const Default &a, const Default &b) const
{
return a.x < b.x;
}
};
struct fy
{
bool operator()(const Default &a, const Default &b) const
{
return a.y < b.y;
}
};
// Sort by x
sort_element(..., fx());
// Sort by x
sort_element(..., fy());
Forget your second class Compare1 and Remove it.
So suppose I have a class like this one:
class Point
{
private:
int x, y;
public:
void setX(int arg_x) { x = arg_x; }
void sety(int arg_y) { y = arg_y; }
int getX() const { return x; }
int gety() const { return y; }
};
Now I want to have a map like this one:
map<Point, Point> m;
But I need a third parameter. I read in cplusplus that this third parameter is to compare something, but I didn't understand what that something was. Can anyone explain that for me?
You can extend your class with such a method if you don't need a separate compare function
class Point
{
private:
int x, y;
public:
bool operator<( const Point& other) const
{
if ( x == other.x )
{
return y < other.y;
}
return x < other.x;
}
};
By default the stl map orders all elements in it by some notion of ordering. In this case this operator is used. Sometimes you dont have control over the Point class or you might want to use it in two different maps each defines its own ordering. For example one map might sort points by x first and other one might sort by y first. So it might be helpful if the comparison operator is independent of the class Point. You can do something like this.
class Point
{
public:
int x, y;
};
struct PointComparer
{
bool operator()( const Point& first , const Point& second) const
{
if ( first.x == second.x )
{
return first.y < second.y;
}
return first.x < second.x;
}
};
map<Point, Point , PointComparer> m;
What you need is to define an ordering of Point items.
This can be done in different ways :
Overload the operator < for Point
You can provide an overload of the < operator, whose prototype is :
bool operator < (const Point & p_lhs, const Point & p_rhs) ;
For example, for my tests, I used the following one :
bool operator < (const Point & p_lhs, const Point & p_rhs)
{
if(p_lhs.getX() < p_rhs.getX()) { return true ; }
if(p_lhs.getX() > p_rhs.getX()) { return false ; }
return (p_lhs.getY() < p_rhs.getY()) ;
}
This is the easiest way, but it assumes, semantically, that the ordering defined above is the right default one.
Providing a functor
If you are unwilling to provide a < operator, or want to have multiple maps, each one with its own ordering, your solution is to provide a functor to the map. This is the third template parameter defined for the map:
template < class Key, class T, class Compare = less<Key>,
class Allocator = allocator<pair<const Key,T> > > class map;
The functor must have the following signature :
struct MyCompareFunctor
{
bool operator() (const Point & p_lhs, const Point & p_rhs)
{
// the code for comparison
}
} ;
So, for my tests, I just wrote the following :
struct MyCompare
{
bool operator() (const Point & p_lhs, const Point & p_rhs)
{
if(p_lhs.getX() > p_rhs.getX()) { return true ; }
if(p_lhs.getX() < p_rhs.getX()) { return false ; }
return (p_lhs.getY() > p_rhs.getY()) ;
}
} ;
And used it in my map:
std::map<Point, Point, MyCompare> map ;
Et voilà...
Specializing std::less for Point
I see no point in doing this, but it's always good to know: You can specialize the std::less template structure for your Point class
#include <functional>
namespace std
{
template<>
struct less<Point> : binary_function <Point,Point,bool>
{
bool operator() (const Point & p_lhs, const Point & p_rhs)
{
if(p_lhs.getX() < p_rhs.getX()) { return true ; }
if(p_lhs.getX() > p_rhs.getX()) { return false ; }
return (p_lhs.getY() < p_rhs.getY()) ;
}
} ;
}
This has the same effect as overloading the operator <, at least, as far as the map is concerned.
As for the operator < solution above, semantically, this solution assumes that the ordering defined above is the right default one as far as std:less is concerned.
Note that the default std::less implementation calls the operator < of the is templated type. Having one giving different results than the other could be considered as a semantic error.
When you are using a user defined class as key in std::map, in order to determine the position of the elements in the container the map needs the Comparison class: A class that takes two arguments of the key type and returns a bool.
It is basically, a comparison functor/ function which compares two key values.
You don't need third parameter, you just need the operator== and operator<
bool operator<(const Point& other) const{
if ( x == other.x )
return y < other.y;
return x < other.x;
}
bool operator==(const Point& other) const{
return x == other.x && y == other.y;
}
I think the code above gives a little upgrade to #parapura rajkumar's solutions.
class Point{
private:
int x, y;
public:
bool operator<( const Point& other) const{
return ((x < other.x) || (y < other.y));
}
};
What you are saying as third parameter is called "Comparator" in STL.
For default types as keys youy don't need to provide one as compiler
does that job for you.
But for your-defined types you have to provide it OR else how would compiler maintain
the sort order in map/set etc.
I am trying sort std::vector using algorithm::sort , But I am getting runtime error
Invalid operator <.
Following is my code.
struct Point {
double x_cord;
double y_cord;
int id;
Point(int d, double x, double y) {
x_cord = x;
y_cord = y;
id = d;
}
};
struct compareX {
bool operator ()(Point * left, Point* right) const {
if (left->x_cord < right->x_cord)
return true;
return true;
}
};
struct compareY {
bool operator ()(Point * left, Point* right) const {
if (left->y_cord <= right->y_cord) return true;
return true;
}
};
Here is now I am calling it after populating the values.
std::sort( posVector.begin(), posVector.end(), compareX());
Your comparison function always returns true!
Your comparison functions always seem to return true. Returning false occasionally might be a good idea. And (to be serious) comparing (x.y) coordinates is not as trivial as it might seem to be - you probably want to think about it a bit before implementing it.
If you are using std::vector<Point> then must be
struct compareX {
bool operator ()(const Point& left, const Point& right) const {
return left.x_cord < right.x_cord;
}
};
struct compareY {
bool operator ()(const Point& left, const Point& right) const {
return left->y_cord < right->y_cord;
}
};
The problems of your code are
comparison classes accept pointers instead of objects being sorted (if std::vector<Point> is sorted, i.e. not std::vector<Point*>). If you are sorting vector of pointers then it is fine.
comparison classes contain mistyping - always return true (as already mentioned)
compareY use <= instead of <. It is bad idea because standard algorithms (including sorting) expect less-semantic (not less_or_equal-semantic).
Overload the '<' operator for the Point class.