overloading operator== comparison 2 class - c++

i'm new in programming and i'm trying to search an element in a list of class and i did this:
string x;
cin >> x;
list<Person>::iterator findIter = std::find(ListPerson.begin(), ListPerson.end(), x);
but it seem like i must overload the operator== to work, i did this:
friend bool operator== (Person &P1, Person &P2);
bool operator== (Person& P1, Person& P2)
{
return (P1.Name == P2.Name);
}
but it doesn't work i got always this error : c2678 binary '==' no operator found which takes a left-hand operand of type Person.
Thank you for helping !

Have you tried declaring the parameters as constant references? A comparison operator does not need to have side-effects.
The following works for me, and prints yeah:
#include <iostream>
using namespace std;
struct P {
const int x;
P(int x) {
this->x = x;
}
};
bool operator== (const P & p1, const P &p2) {
return p1.x == p2.x;
}
int main()
{
P x(0), y(0), z(1);
if (x == y) {
cout << "yeah" << endl;
}
if (y == z) {
cout << "nope" << endl;
}
}
Of course you might need to declare the operator== as a friend function if you want to do a comparison over private instance variables.
class P {
int x;
public:
P(int x) {
this->x = x;
}
friend bool operator== (const P &p1, const P &p2);
};

Your friend bool operator== declaration should be inside the class declaration. Next, pass by const reference instead, as rvalues cannot bind to non-const references and also the std::find expects its compared-to element by const reference. So your operator== should be able to compare const references, and non-const ones will not do since they will discard const qualifiers. To fix, declare
friend bool operator==(const Person &P1, const Person &P2);
Live working example here.

Related

What does < (less-than sign) between a function identifier and a function parameter mean? [duplicate]

This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed last month.
struct point {
int x, y;
bool operator<(const point &p) {
if (x == p.x) return y < p.y;
else return x < p.x;
}
};
What does < between operator and (const point &p) signify?
What does < between operator and (const point &p) signify?
It's a part of the member function name. It is a definition of a member function which is an overload of the < operator. It is what makes this work:
point a{};
point b{};
if(a < b) { // point::operator<(const point&) is used here.
//
}
Note: The member function should really be const qualified because calling the function does not change *this (the lefthand side of <).
bool operator<(const point &p) const {
// ^^^^^
... and it's also preferable if it's not even a member function, but a free function (taking two const point&):
bool operator<(const point& lhs, const point &rhs) {
return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}
This is because if point has an implicit conversion constructor, it will allow an instance of a type that is implicitly convertible to point to appear on both the lefthand and righthand side of <.
Example:
struct point {
point(int X, int Y) :x{X}, y{Y} {}
point(const std::pair<int, int>& pair) : x{pair.first}, y{pair.second} {}
int x, y;
};
bool operator<(const point& lhs, const point &rhs) {
return std::tie(lhs.x, lhs.y) < std::tie(rhs.x, rhs.y);
}
int main() {
std::pair<int, int> ip{10,20};
point pnt{10,19};
// This works with operator< as a member function or a free function:
if(pnt < ip) std::cout << "pnt < ip\n";
// This will not work if `operator<` is a member function:
if(ip < pnt) std::cout << "ip < pnt\n";
// ^^
// implicitly converted to `point`
}

Compare two objects in vector iteration C++

How to implement the comparison function in this case?
void remove(const Object1 &object1) {
for(auto &object2 : objectVector) {
if(object1 == object2) {
/*....... */
}
}
}
You are asking 2 questions:
How can objects be made comparable:
By implementing operator== for the class. Be sure you override operator != then too.
As a member function:
bool Object1::operator ==(const Object1 &b) const
{
// return true if *this equals b;
}
Or as a free function:
bool operator ==(const Object1 &a, const Object1 &b)
How can objects with a given value be removed from a vector:
The easiest way is to use std::remove:
objectVector.erase(std::remove(objectVector.begin(), objectVector.end(), object1), objectVector.end());
You can remove objects also while iterating through the vector, but you have to keep in mind that the vector iterator is invalidated then. You may not further iterate on the vector then.
An object of your class can contain different types and number of members so let's say that you have a class A:
class A{
int x,
float y;
char* z;
};
And you have two instances:
A a1;
A a2;
To compare:
if(a1 == a2) // compile-time error
;// DoSomeThing
Above you get the error because the compiler doesn't know which fields will be compared against each other. The solution is to overload the equals operator "==" to work on objects of your class.
class Student{
public:
Student(std::string, int age);
std::string getName()const;
int getAge()const;
bool operator == (const Student&);
private:
std::string name;
int age;
};
Student::Student(std::string str, int x) :
name(str), age(x){
}
bool Student::operator == (const Student& rhs){
return age == rhs.age;
}
std::string Student::getName()const{
return name;
}
int Student::getAge()const{
return age;
}
int main(){
Student a("Alpha", 77);
Student b("Beta", 49);
if(a == b)
std::cout << a.getName() << " is the same age as " <<
b.getName() << std::endl;
cout << endl << endl;
return 0;
}
Now the compiler knows how to compare objects of your class and know what the equals operator compares on your ojects members.
if object is a class you can override the operator == in the class as a friend function, or you can implement your own function bool isEqual(Object1 o1, Object1 o2) { if(something) return true; return false; }

const qualifier end of function

#include <iostream>
using namespace std;
class Point {
private:
int x, y; // Private data members
public:
Point(int x = 0, int y = 0); // Constructor
int getX() const; // Getters
int getY() const;
void setX(int x); // Setters
void setY(int y);
void print() const;
const Point operator+(const Point & rhs);
// Overload '+' operator as member function of the class
};
int main(int argc, char** argv)
{
Point p1(1, 2), p2(4, 5);
// Use overloaded operator +
Point p3 = p1 + p2;
p1.print(); // (1,2)
p2.print(); // (4,5)
p3.print(); // (5,7)
// Invoke via usual dot syntax, same as p1+p2
Point p4 = p1.operator+(p2);
p4.print(); // (5,7)
// Chaining
Point p5 = p1 + p2 + p3 + p4;
p5.print(); // (15,21)
return 0;
}
// Constructor - The default values are specified in the declaration
Point::Point(int x, int y) : x(x), y(y) { } // Using initializer list
// Getters
int Point::getX() const { return x; }
int Point::getY() const { return y; }
// Setters
void Point::setX(int x) { this->x
= x; } // (*this).x = x; x = x
void Point::setY(int y) { this->y = y; }
// Public Functions
void Point::print() const {
cout << "(" << x << "," << y << ")" << endl;
}
// Member function overloading '+' operator
const Point Point::operator+(const Point & rhs) {
return Point(x + rhs.x, y + rhs.y);
}
I'm studying operator overloading and I don't understand why I get the error.
error: no match for 'operator+' (operand types are 'const Point' and 'Point')
I deleted const qualifier at the end of the operator+ function on purpose in order to understand it. Can someone explain explicitly why I need it?
The member
const Point Point::operator+(const Point & rhs);
is a non-const member, i.e. requires the lhs of the operation to be mutable, but (as the error message shows) you require an operation with a const lhs. Hence, you must declare the operator as such
Point Point::operator+(const Point & rhs) const;
Note that I also removed the const for the return type, as it is deprecated.
Why do you need the const? The natural + operator (for example between arithmetic types) does not alter its arguments and, as a consequence, the usual (human) conventions for using this operator implicitly assume that the arguments are not altered. In your particular case, the return of a+b was explicitly const (though that is deprecated AFAIK), so that in a+b+c = (a+b)+c the lhs is const and your non-const member function cannot be used.
Moreover, whenever a member function does not alter the state of its object, it should be declared const, so that it can be called for const object.
Alternatively, this operator can be defined as non-member function friend
Point operator+(const Point&lhs, const Point&rhs);
which more clearly expresses the symmetry between lhs and rhs (the corresponding function for your non-const member would have been
Point operator+(Point&lhs, const Point&rhs);
).
You need to define your method as a constone, i.e.:
const Point operator+(const Point & rhs) const;
p1+p2 returns a const Point so you need a const Point + const Point operator to be able to compute (p1+p2)+p3.
Good answers, but they don't explain why the const is an issue. The simple reason is chaining order and operator type matching.
Point p5 = p1 + p2 + p3 + p4;
// is interpreted as:
Point p5 = ConstPoint( (Point(p1)).operator+((const Point&)(p2)) + p3 + p4;
// as operator+ is left-to-right , not right-to-left !!!
Point and const Point are different types, so in the first iterpretation, you have a:
p5 = const Point(sumP1P2) . operator+ (Point(P3)) /*+ P4 awaiting interpretation */;
// whose search will be for a const LHS - i.e. "Point operator=(constPointRef) const;" - which is bound to fail.
The following will work:
const P& operator+(const P& rhs) const; // corresponds to const P& result = const P& lhs + const P& rhs
P operator+(P rhs) const; // corresponds to copy-by-value for all operands.
The only problem is "const" Point operator+(const Point & rhs); remove that in the def and dec .. it will work

overload greater than operator with or without friend

Suppose I have the following class:
class Point{
private:
int x,y;
public:
int get_x() const {return x;}
int get_y() const {return y;}
Point() :x(0),y(0){}
Point(int x,int y):x(x),y(y){}
Point(const Point& P){
x = P.get_x();
y = P.get_y();
}
Point& operator= (const Point& P) {
x = P.get_x();
y = P.get_y();
return *this;
}
friend ostream& operator<<(ostream& os,const Point& P) {
os<<"["<<P.get_x()<<", "<<P.get_y()<<"]";
return os;
}
Point operator - (const Point &P){
return Point(x-P.get_x(),y-P.get_y());
}
friend bool operator > (const Point &A, const Point &B) {
return A.get_y()>B.get_y();
}
};
Here I used friend function. I can also use function without friend:
class Point{
...
bool operator > (const Point &B) const {
return y>B.get_y();
}
...
};
What are the differences between them in actual implementations? Also in the second method, the code won't compile without 'cont', why is that? Even after I changed the getter function into non-const function, it still won't compile without the 'const'.
As you've already noticed, comparison operator overloads can either be implemented as a member function or as a non-member function.
As a rule of thumb you should implement them as a non-member non-friend function where possible, as this increases encapsulation, and it allows (non-explicit) conversion constructors to be used on either side of the operator.
Say for instance your Point class for whatever reason had an int conversion constructor:
Point(int x);
With a non-member comparison operator you can now do the following:
Point p;
p < 3; // this will work with both a member and non-member comparison
3 < p; // this will **only** work if the comparison is a non-member function
You also seem to be confused about when to use const, again as a rule of thumb for comparison operators you should always use const wherever possible, because comparisons logically do not involve any change to the object.
As Point is a very small class you could also take it by value instead, so in order of most to least preferable your options are:
// Non-member, non-friend
bool operator>(Point const& A, Point const& B);
bool operator>(Point A, Point B);
// Non-member, friend
friend bool operator>(Point const& A, Point const& B);
friend bool operator>(Point A, Point B);
// Member
bool Point::operator>(Point const& B) const;
bool Point::operator>(Point B) const;

C++ Bool Operator==

I just tried to make a function that compares 2 objects, but it gives me:
Error: bool Duree::operator==(const Duree&, const Duree&) must take exactly one argument
How can I solve this? Thank you.
Duree.h
#ifndef DEF_DUREE
#define DEF_DUREE
class Duree
{
public:
Duree(int heures = 0, int minutes = 0, int secondes = 0);
bool estEgal(Duree const& b) const;
bool operator==(Duree const& a, Duree const& b);
private:
int m_heures;
int m_minutes;
int m_secondes;
};
#endif
Duree.cpp
#include "Duree.h"
Duree::Duree(int heures, int minutes, int secondes) : m_heures(heures), m_minutes(minutes), m_secondes(secondes)
{
}
bool Duree::estEgal(Duree const& b) const
{
return (m_heures == b.m_heures && m_minutes == b.m_minutes && m_secondes == b.m_secondes);
}
bool operator==(Duree const& a, Duree const& b)
{
return a.estEgal(b);
}
Main.cpp
#include <iostream>
#include "Duree.h"
using namespace std;
int main()
{
Duree fisrt(10, 10, 10), second(15, 20);
if (fisrt == second)
cout << "Les durees sont identiques";
else
cout << "Les durees sont differentes";
return 0;
}
Either you declare operator== as a free function with two arguments:
bool operator==(Duree const& a, Duree const& b);
or as a member function with only one argument:
bool Duree::operator==(Duree const& b);
This is because when you do x == y you are comparing only two objects. If you have a member function there's an implicit "this object" (the one you call operator== on) passed, making it 3 arguments instead of 2.
That being said, from the way you wrote the code I'm guessing you just forgot to put friend in front of the operator== declaration, in the class definition.
Probably useful tip: You can use #pragma once, on compilers that support it (basically every "main" compiler), instead of include guards. :)
Change your prototype to bool operator==(Duree const& rhs); or make it a free function out of class Duree.
Always prefer the binary functions to be NON MEMBER (free) functions. Otherwise you can run into problems if you overload the operator with different types. Consider the following contrived code:
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
};
This should work fine for comparing two Foos together. But it has a problem.
Suppose you also want to compare to an int:
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
bool operator==(int other) const { return x == other; }
};
Now you can compare one way but not the other:
Foo a, b;
...
a == b; // ok
a == 123; // ok
123 == a; // ERROR
As member function the object must be on the right hand side.
Simple, move the int-Foo overloads out of the class, and make two versions, Foo==int and int==Foo? (Note, making them friends declared inside the class can accomplish that too, FWIW, but I'm not showing it here.)
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
};
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }
So now everything works, right? We have a mix of member and non-member operators.
a == b; // ok
a == 123; // ok
123 == a; // ok
Until Foo starts getting member functions that want to use the operators...
struct Foo {
int x;
bool operator==(Foo const & other) const { return x == other.x; }
void g(int x);
};
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }
void Foo::g(int x)
{
Foo f = getOtherFoo();
if (f == x) { // ERROR! cannot find operator==(Foo,int)
//...
}
}
It STILL has a problem! Inside members of of Foo, it cannot see the non-member operators because the member one hides them! g() will not compile since it can't compare Foo to int. Moving all of the operators out will resolve it, since then all of the overloads are in the same scope.
(Remember, name-lookup keeps searching outer scopes UNTIL it finds the fist case of the name it is looking for, and then only considers all the names it finds in that scope. Inside g(), it's scope is in the class, and since it finds one version of the operator inside the class (the wrong one), it never looks outside the class for more overloads. But if they are all outside the class, it'll find them all at the same time.)
struct Foo {
int x;
void g(int x);
};
// NON MEMBER
bool operator==(Foo const & lhs, Foo const & rhs) { return lhsx == rhs.x; }
bool operator==(int other, Foo const& f) { return f.x == other; }
bool operator==(Foo const& f, int other) { return f.x == other; }
void Foo::g(int x)
{
Foo f = getOtherFoo();
if (f == x) { // OK now, finds proper overload
//...
}
}
Now, it compiles in all the cases. That's why they say, "Always prefer to make non-member binary operator overloads." Otherwise you can end up with symmetry and hiding problems.
I'm on the same kind of issue.
Worked by putting operator== with two arguments back in main.cpp before the main() ;)