Problem with operator == - c++

I am facing some problem with use of operator == in the following c++ program.
#include < iostream>
using namespace std;
class A
{
public:
A(char *b)
{
a = b;
}
A(A &c)
{
a = c.a;
}
bool operator ==(A &other)
{
return strcmp(a, other.a);
}
private:
char *a;
};
int main()
{
A obj("test");
A obj1("test1");
if(obj1 == A("test1"))
{
cout<<"This is true"<<endl;
}
}
What's wrong with if(obj1 == A("test1")) line ?? Any help is appreciated.

strcmp returns 0 when the strings are equal, so you want:
return strcmp(a, other.a) == 0;
You should also use a const reference like Cătălin Pitiș says in his answer, because then you can use temporary objects with the operator, and you should also make the method itself const (since it doesn't modify the object) as Andreas Brinck says in the comments below. So your method should be:
bool operator ==(const A &other) const
{
return strcmp(a, other.a) == 0;
}

bool operator ==( const A &other)
Use const reference, so a temporary object that is constructed in if statement can be used as parameter for operator==.

It looks to me like you want this in your operator:
strcmp(a, other.a) == 0
strcmp returns 0 when strings match, and a number indicating whether the comparison is greater or less than otherwise.

Your error is that you create an instant value and pass it as reference to the operator== method. But your error is in your operator definition that should be:
bool operator==(const A& other) const
the body being the same.

Related

C++17 operator==() and operator!=() code fails with C++20

I've got the following sample code:
#include <assert.h>
struct Base
{
bool operator==(const Base& rhs) const
{
return this->equalTo(rhs);
}
virtual bool equalTo(const Base& rhs) const = 0;
};
inline bool operator!=(const Base& lhs, const Base& rhs)
{
return !(lhs == rhs);
}
struct A : public Base
{
int value = 0;
bool operator==(const A& rhs) const
{
return (value == rhs.value);
}
virtual bool equalTo(const Base& rhs) const
{
auto a = dynamic_cast<const A*>(&rhs);
return (a != nullptr) ? *this == *a : false;
}
};
class A_1 : public A
{
virtual bool equalTo(const Base& rhs) const
{
auto a_1 = dynamic_cast<const A_1*>(&rhs);
return (a_1 != nullptr) ? *this == *a_1 : false;
}
};
int main()
{
A_1 a_1;
a_1.value = 1;
// Make sure different types aren't equal
A a;
a.value = 1;
assert(a_1 != a);
}
When I compile with C++17, everything is fine (no assert, as desired). Building the same code with C++20 causes the assert to fire.
How can I get this existing code to work when compiling with C++20? If I crank up the warnings, with C++20, I get 'operator !=': unreferenced inline function has been removed; I suspect this is all somehow related to operator<=>().
Is this really a known/desired breaking change from C++17 to C++20?
In C++17, the line
assert(a_1 != a);
Invokes operator!=(const Base&, const Base&), because of course, it's the only candidate. That then invokes a_1->equalTo(a), which tries to downcast a to an A_1, which in your logic gives you false. So a_1 != a evaluates as true.
In C++20, we now additionally consider rewritten candidates in terms of ==. So now we have three candidates:
Base::operator==(const Base&) const (rewritten)
A::operator==(const A&) const (rewritten)
bool operator!=(const Base&, const Base&)
Of these, (2) is the best candidate, since it's a better match for the two parameters. So a_1 != a evaluates as !((const A&)a_1 == a), which gives you a different answer.
However, your operators are fundamentally broken. Even in C++17, we had the scenario that a_1 != a evaluates as true while a != a_1 evaluates as false. This is basically the inherent problem of trying to do dynamic equality like this: this->equalTo(rhs) and rhs.equalTo(*this) might actually do different things. So this issue is less of a C++20 comparisons issue and more of a fundamental design issue.

Why is this assert failing?

The assert in main.cpp is failing, and I don't understand why.
Here is string.hpp
class String
{
private:
int len;
char* str;
public:
String(char const* s); // C-string constructor
~String() {delete str;}; // destructor
char* const getString(); //get string for printing
};
inline bool operator==(String lhs, String rhs)
{
return std::strcmp(lhs.getString(),rhs.getString());
}
// Define operator!= in terms of ==
inline bool operator!=(String const& lhs, String const& rhs)
{
return !(lhs == rhs);
}
and here is string.cpp
String::String(char const* s) // C-string constructor
{
len = std::strlen(s);
str = new char[len+1];
std::strcpy(str,s);
}
char* const String::getString()
{
return str;
}
and here is main.cpp
#include <cassert>
int main()
{
String c = "c";
String d = "d";
assert(c == c);
assert(c != d);
}
I tried to include only the essential code. I left out a lot of the obvious includes. The assert(c == d) is failing and I don't understand why. The operator overload of == should have returned a true result.
std::strcmp returns 0 if the strings are equal. So your operator== will return false for equal strings and true else.
You could, for instance, switch the implementations of == and != around,
strcmp returns 0 when its arguments have equal contents.
So add a comparison with 0 to your operator==:
inline bool operator==(String const& lhs, String const& rhs)
{
return std::strcmp(lhs.getString(), rhs.getString()) == 0;
}
Also, since you probably don't want to copy the arguments each time you call operator==, I'd recommend passing them by reference.

How to overload operator ==?

I have class A
how to overload operator == to perform
A a,b,c;
if (a==b==c) {}
Could anyone help me?
Very short answer: NO!
Slightly longer answer: Don't try this.
Explanation: Every C++ programmer is used to have the comparison operator return a bool or something convertible to bool. Just because it's natural to type things like if (a==b).
So if the expression a==b returns a bool x, then a==b==c would mean comparing x with c. Which makes no sense at all. Even if you get it to compile, e.g. comparing ints that way, it would not yield the result you expect.
So, while there technically I can think of a solution to what you seem to want (compare if all three are equal), the right thing to do is how it is always done in C++: logically chain binary comparisons:
if (a==b && b==c) {}
for the ones who wonder about the "technical doable but oh so ugly" solution:
(DON'T DO THIS IN REAL WORLD USE! You should get fired if you do.)
template <class T>
struct multiCompareProxy {
bool b;
T const& t;
explicit operator bool() const {return b;}
multiCompareProxy operator==(T const& rhs) {
return {b && t.equals(rhs), t};
}
};
template <class T>
multiCompareProxy<T> operator==(T const& lhs, T const& rhs) {
return {lhs.equals(rhs), lhs};
}
A class now just has to overload the euqals method for this to work: Example
If for whatever reason you really wanted to do this, you'd need a proxy object like so:
struct A {};
struct Proxy {};
Proxy operator==(const A& a, const A& b) {
return {};
}
bool operator==(const Proxy& p, const A& b) {
return true;
}
bool operator==(const A& a, const Proxy& p) {
return true;
}
#include <iostream>
int main() {
A a, b, c;
if(a == b == c) {
std::cout << "Bad.\n";
}
}
But don't do this. Use (a == b) && (a == c) like everyone else.
It can be done, and it's very occasionally useful as a kind of domain-specific language (DSL) for matching the notation expected by non-C++-programmers, but it should be studiously avoided for other uses as it'll confound (and annoy) programmers working on the code if this is used willy-nilly.
class A
{
// ...
bool equals(const A& rhs) const { return ... }
struct X
{
X(const A& a, bool b) : a_(a), b_(b) { }
X& operator==(const A& rhs) const { b_ &= a_.equals(rhs); return *this; }
explicit operator bool() const { return b_; }
// remove explicit pre C++11 / consider making it operator void*() ...
const A& a_;
mutable bool b_;
};
X A::operator==(const A& rhs) const
{
return X(*this, equals(rhs));
}
};
(You might prefer standalone functions if you have implicit constructors).
The same kind of proxy-using hackery allows all manner of unexpected notations like 3 < x < 9 and x == a1 || a2 || a3... again, avoid them unless it'll make a huge difference to the maintainers of the code where they'll be used (and ideally that code will have very clear boundaries from the other C++ code in your system).
As an example of good uses of such techniques, consider the boost spirit library and it's unusual use of a lot of operators to provide something approximating BNF notation....
You cannot (minus the possibility of an ugly hack) overload operator==(...) to work as you have specified.
If you think about what it would do a == b would become either true or false (a bool), then you would have (<bool> == c) left. The proper way to do what you are looking to do would be some form of (a==b) && (b==c).
There are times when you can overload an operator to work as you describe, but it would have to return the same type that it takes. An example would be:
class A
{
A& operator+=(A const& rhs)
{
// operator logic
return *this;
}
}
This case works because with a += b += c, you would perform (b += c) which would return an A&, which the remaining a.operator+=(...) accepts as an argument.
bool operator==(T const & a, T const & b) {
return /*boolean expr*/
}
if you have a class you can do:
class MyClass {
public:
bool operator==(T const & rhs) const {
return /*boolean expr*/
}
}
And don't use == twice in a row, you can't, do:
a == b && b == c
I would write:
bool operator==(const A& lhs, const A& rhs){ /* do actual comparison */ }
And use it twice with and operation.

Calling an overloaded == operator in a different function that checks for !=

I am trying to write an operator != function that compares if two complex numbers are the same. I Have written an equal to == function which works well but I am trying to use the negation of the result.
bool ComplexNumber::operator !=(ComplexNumber a) {
return !(this==(a)); //the == has been overloaded
}
return !(this==(a)); is comparing a ComplexNumber* to a ComplexNumber. Change to:
bool ComplexNumber::operator !=(const ComplexNumber& a) const {
return !(*this == a); //the == has been overloaded
}
Also added const qualifier to function and argument (which I changed to to a reference to avoid unnecessary copy). You will need to add const qualifier to bool ComplexNumber::operator ==() if it is not already present.
Please rewrite your post as a question.
I guess the question is: Why doesn't this work. The problem you have is that this is a pointer to an object, while a is an object.
bool ComplexNumber::operator !=(ComplexNumber a){
return !(*this==(a)); //the == has been overloaded
}
will solve your problem.
bool ComplexNumber::operator !=(const ComplexNumber &a) const {
return !operator==(a);
}

Error using std::find with operator==

I am getting an error using std::find on the following structure ...
struct ComplianceOrderRecord {
explicit ComplianceOrderRecord(IOrder& order);
bool operator ==(const ComplianceOrderRecord& other) const;
double price;
};
inline bool ComplianceOrderRecord::operator ==(const ComplianceOrderRecord& other) const {
return price == other.price;
}
I use it as follows...
inline void Compliance::RemoveComplianceOrderRecord(const ComplianceOrderRecord& order) {
auto it = std::find(m_compliantOrderList.begin(),
m_compliantOrderList.end(), order);
if(it == m_compliantOrderList.end()) {
return;
}
m_compliantOrderList.erase(it);
}
The error is...
error C2679: binary '==' : no operator found which takes a right-hand operand of type 'const ComplianceOrderRecord' (or there is no acceptable conversion)
Any help in understanding this error would be very appreciated.
Your operator== should be a const member, or even better, a freestanding function.
This error can be reproduced if m_compliantOrderList is not a container<ComplianceOrderRecord >. (Perhaps it is a container of pointers, or some other completely unrelated class.
Edit:
Your equality operator can compare two instances of ComplianceOrderRecord, but find needs to compare a pointer against an object. Overloading an operator to perform this kind of comparison would be bizarre, so you could use find_if with a custom predicate, such as:
struct RecordIsEqualTo
{
const ComplianceOrderRecord* record;
RecordIsEqualTo(const ComplianceOrderRecord& r): record(&r) {}
bool operator() (const ComplianceOrderRecord* r) const { return *record == *r; }
};
std::find_if(m_compliantOrderList.begin(), m_compliantOrderList.end(),
RecordIsEqualTo(order) );
or a lambda version thereof.
Your operator== function should be const. As it is, you can't call it on a const object (or a reference to const.
Try a const method:
inline bool ComplianceOrderRecord::operator ==(const ComplianceOrderRecord& other) const {
return price == other.price;
}