What is the difference between these two ways of overloading the != operator below. Which is consider better?
Class Test
{
...//
private:
int iTest
public:
BOOL operator==(const &Test test) const;
BOOL operator!=(const &Test test) const;
}
BOOL operator==(const &Test test) const
{
return (iTest == test.iTest);
}
//overload function 1
BOOL Test::operator!=(const &Test test) const
{
return !operator==(test);
}
//overload function 2
BOOL Test::operator!=(const &Test test) const
{
return (iTest != test.iTest);
}
I've just recently seen function 1's syntax for calling a sibling operator function and wonder if writing it that way provides any benefits.
Your first overload ensures that calling != on your type will always provide the opposite of calling == even if your implementation of == would change.
Your second overloaded function does not, since it is possible to provide any implementation for == and change the existing implementation in the future.
If you want to ensure that != will always be the opposite of ==, go with the first (at the cost of an extra function call which may very well become inlined anyway).
Here is a good example. Suppose that you have a class Point2D with fields x and y. If you want to implement ==, you will have to compare on field x and on field y. If you implement != by calling operator==, you have shorter code, and will have one function less to change if you ever moved to a polar representation.
Equality tests and comparisons are always susceptible to maintenance errors as the class fields change. Minimizing the number of methods that directly access state can reduce the risk of errors.
They will almost certainly compile to the same machine code.
I prefer choice 2, just because I find it awkward to say "operator==". But you could have used
return ! (*this == test)
And IMHO that's also clear and easy to understand.
I can think of many reasons (or perhaps aspects of the same reason) to write it that way. What they all boil down to is: it's DRY.
It ensures that two objects are always either == or !=
If you decide to change what's in the class, or what's used for equality testing, you only have to change it in one place
I think that conceptually, you really have two different things you're defining here:
A definition of "equality" for class Test
A useful interface by which people using this class can determine equality of their instances
With method 2, you're doing both ad-hoc. With method 1, you're defining equality in operator==, and providing the rest of the interface via operator!=.
Some languages/libraries take it even further, e.g., in Ruby you can define just <=> to compare ordered objects and mix-in Comparable and get equality, inequalities, and between?.
Version #1, while syntacticly ugly IMHO, allows you to change the equality logic in a single place (in the == operator overload). It guarantees the two overloads are always in sync.
In general, the following statement:
return !(*this == object);
allows you to define != in terms of one function. In the world of inheritance, child objects would only need to define operator== in order to use the base class operator!=:
struct Base
{
virtual bool isEqual(const Base& other) const = 0;
bool operator==(const Base& other) const
{
return isEqual(other);
}
bool operator!=(const Base& other) const
{
return !(*this == other); // Uses Base::operator==
}
};
With the above base class, defining operator!= using != would require descendants to implement more methods.
Also, !(*this == other) allows one to define a global, generic function for !=:
template <typename T>
bool operator!=(const T& a, const T& b)
{
return !(a == b);
}
Although this pattern doesn't provide much for == and !=, the differences are larger when using the relational operators: <, <=, >, >=.
In general, it is always better to implement related functionality in terms of each other. In case of operators, there are always groups. For example, != can be implemented in terms of ==; post-increment can be implemented in terms of pre-increment; >, <= and >= can be implemented in terms of < (see std::rel_ops in <utility>) etc. If something about the class needs changing, you only need to modify the core operators, and all the rest will automatically be updated to reflect the new behavior.
The general implementation of all the "secondary" operators is always the same, and so there is even a library which automatically provides operators that are defined in terms of a few provided ones. See Boost.Operators
Your example:
#include <boost/operators.hpp>
class Test : boost::equality_comparable<Test, Test>
{
private:
int iTest;
public:
bool operator==(const Test& test) const;
//look, no operator !=
};
int main()
{
Test a, b;
a != b; //still works
}
Related
apologies in advance if this question is stupid but:
I have an interface:
template <class T>
class IEqualCompare {
public:
virtual bool IsEqual(const T b) = 0;
bool operator== (const T b) { return this->IsEqual(b); } //Both are implemented in cpp file
bool operator!= (const T b) { return !(this->IsEqual(b)); }
};
And a class:
class Dimentions : IEqualCompare<Dimentions> {
...
bool IsEqual(const Dimentions b) { //IsEqual logic for this specific class }
...
}
I would like to only implement IsEqual method for each child class of IEqualCompare, as the logic within the operator overloads (==, !=) is the same for any IEqualCompare derived class.
Up until now I have always simply defined both operator overrides as virtual and implemented them inside each class, but as the logic should be always the same I wanted to know if this is possible or is it bad programming.
Thanks in advance for any answers.
First of all, since comparison operators are usually not meant to modify compared objects, they (and IsEqual method) should be declared const as a general practice of const correctness. Among other things it helps programmers avoid mistakes of accidentally modifying objects during semantically non-modifying operations and helps optimizers produce more efficient binaries by utilizing more assumptions about code behaviour. Also, to avoid unnecessary copying the argument of operators should generally be taken by reference, in our case by const reference so that referenced object can't be modified.
Now, if you want to just automatically add equality comparison operators to derived classes based on their IsEqual method and not to use dynamic polymorphism/dispatch (it would be pretty pointless for CRTP base), there's no need to make IsEqual virtual, or even a member of base class at all. Derived type is provided as template parameter type T, so you statically know actual (dynamic) object type (this is the whole point of CRTP pattern you use), thus you can statically cast this pointer to T* and call non-virtual IsEqual method of T through resulting pointer avoiding the more costly virtual dispatch mechanism. Example:
template<typename T>
class AddEqualComparisons {
public:
bool operator==(const T& b) const { return static_cast<T*>(this)->IsEqual(b); }
bool operator!=(const T& b) const { return !static_cast<T*>(this)->IsEqual(b); }
};
class Dimensions : public AddEqualComparisons<Dimensions> {
bool IsEqual(const Dimensions& rhs) const {
// ...
}
};
Your solution is not necessarily bad, it is an application of the "template method" design pattern. It does read like C#/Java-style code to me, which is perhaps unconventional in C++ for this purpose.
The convention in C++ has been to just write each operator!= in terms of operator==. With compilers now supporting C++20, the complementary operator can be generated automatically, removing the need to write a trivial expression like !(x == y). Something like this is often all you need to make your class equality-comparable:
class Foo {
friend bool operator==(Foo const&, Foo const&) = default;
};
If the subobjects of the class (its base classes and member variables) are all equality_comparable, then the above syntax will produce a default comparison operator that compares the two sets of subobjects. You can of course create your own definition if you need to deviate from this.
Note that declaring the operator as a non-member friend function is just my preference, the member function syntax is equally valid.
In making a class, the compare method and the operator== overload should have identical functionality. Therefore, only one implementation is needed, and I'm trying to figure out if there's any reason why it should be defined in the compare method rather than the operator== overload.
Here's the structure defining comparison in compare:
class T {
// definition of field f
...
bool compare(const T& t) const {
if (this->f == t.f) { return true; }
return false;
}
friend bool operator == (const T& lhs, const T& rhs) { return lhs.compare(rhs); }
}
versus in the operator == overloading:
class T {
// definition of field f
...
bool compare(const T& t) const { return *this == t; }
friend bool operator == (const T& lhs, const T& rhs) {
if (lhs.f == t.f) { return true; }
return false;
}
}
TL;DR use second variant with 'virtual' keyword, but it will be better to get rid of this bullshit at all and use operator== only
You should use method compare() only if you have other variant of objects comparison, otherwise it does not make any sense. The reason for this is implementation of std::map, std::set, sorting alghoritms, etc., which use operator==, so if you use first variation of == implementation it will be, basicaly, your operator==, but with other name, which does not make any sense.
If you still want to do it,
-You can use first variant(where == uses compare), but make compare method virtual. In this case you will be able to overload comparison method just like in Java and it will affect on comparison, but still you can do it just by creating operator== for children class, so it still doesn't make any sense
...or you can use second one, but still using 'virtual' keyword to change implementation of parent class in children classes and if you don't like == implementation you can use compare method
Not very relatable example, but I think it might help you. In OpenCV library assignment operator= for class Mat(this class contains literally array of pixels and nothing more) don't actually copies array, but copies only a pointer on array of pixels(because it's heavy operation and it doesn't required in many cases), and for actual copying method clone() used. I think you can use the same solution for your code
class classN
{
public:
bool operator== (const classN &o) const {//some logic here};
bool operator!= (const classN &o) const {return !(*this == o);};
};
I see this as the best way to write overloads of operator== and operator!=, as I need to change code only once. however, I've seen in different projects people writing actual code in both overloads. As I mention, I feel it's quite a big downside that if logic will be changed it should be changed in two places, with can leads to a bugs when you will forget to make similar change in other overload. But maybe there are some downsides I'm not aware of writing the way I've shown now, using return !(*this == o); ? Like calling to a operator== overload inside operator!= being too expensive, so it makes sense to write actual code with comparison of the class fields? Or something else?
In my program, I use many arma::uvecs, and check equality between them like this
#include <armadillo>
using Vec = typename arma::uvec;
Vec v1({0, 0});
Vec v2({0, 1});
bool are_equal = arma::all(v1 == v2);
as I couldn't find any better equality operator in the Armadillo docs. Now that works perfectly fine, but to save some space, and as an exercise in subclassing and operator overloading, I want to define the equality sign directly between the vectors like this:
class Vec : public arma::uvec {
friend bool operator==(const Collapsed& lhs, const Collapsed& rhs) {
return arma::all(lhs == rhs);
}
};
But sadly, I can't get it to work like that. I'm grateful about any hints!
Operator overloads do not need to be part of a class. I would suggest implementing your comparison operator as a free function like this:
bool operator==(const arma::uvec& lhs, const arma::uvec& rhs) {
return arma::all(lhs == rhs);
}
Regarding the friend in your question: As a quick summary, it provides the function that is befriended access to private and protected members of the class where the friend declaration is located. It it is not used to implement functions.
You can read more about it on cppreference or on this SO question
EDIT
Since the above only works if operator== is not already defined, here is a version that overrides it's implementation for a custom subclass:
class Vec : public arma::uvec
{
public:
bool operator==(const Vec& other)
{
// depending on wether arma implemets operator== as member or free function
// return arma::all(this->arma::uvec::operator==(other));
return arma::all(arma::operator==(*this, other));
}
};
Problem is library itself:
Armadillo: C++ library for linear algebra & scientific computing
operators: + − * % / == != <= >= < > && ||
Overloaded operators for Mat, Col, Row and Cube classes
Operations:
+ addition of two objects
− subtraction of one object from another or negation of an object
* matrix multiplication of two objects; not applicable to the Cube class unless multiplying by a scalar
% element-wise multiplication of two objects (Schur product)
/ element-wise division of an object by another object or a scalar
== element-wise equality evaluation of two objects; generates a matrix/cube of type umat/ucube
!= element-wise non-equality evaluation of two objects; generates a matrix/cube of type umat/ucube
and uvec is:
uvec = ucolvec = Col<uword>
so operator== is already there and its functionality is strange/unexpected.
My recommendation is: do not fight with a library. Do not try provide own operator. Just provide a named function areEqual.
Defining a class just to provide own equal operator is not a best choice and if doing that then IMO it is better to use composition not inheritance (depending on requirement it will be more boiler plate code in class itself, but it will be easier to avoid unexpected behaviors).
I'm a bit confused about using STL set::find() for a set of my own defined class objects.
My class contains more than two items (3/4/5 etc.), so how can I overload less operator?
I tried for 3 variable, which is as follows and working fine:
return( (a1.i < a2.i) ||
(!(a1.i > a2.i) && (a1.f < a2.f)) ||
(!(a1.i > a2.i) && !(a1.f > a2.f) && (a1.c < a2.c)));
where, a1, and a2 are class objects and (i, f and c are class members).
Now I want to generalize this for n members, but my find() does not always work.
I've been looking through STL's detailed documentation, trying to learn how set::find() is implemented, and why it needs less (<) operator overloading.
I referred to sgi and msdn documentation, but I could not find much about implementation details of set::find() there, either.
What am I doing wrong in my set::find() implementation?
You can use a tuple to easily get an lexicographical ordering of your members:
return std::tie(lhs.i, lhs.f, lhs.c) < std::tie(rhs.i, rhs.f, rhs.c);
This requires that every member be of a comparable type, e.g. lhs.i < rhs.i makes sense.
Note that std::tie and std::tuple are only available for C++11, so for C++03 you can use e.g. Boost.Tuple which does provide a boost::tie (boost::tuple uses the same ordering as std::tuple).
As to where this should go, it is customary to put that in an operator< (after all this is what make the use of tie for an easy ordering possible in the first place). Quite often this operator will be a friend, so this would look like:
class foo {
public:
/* public interface goes here */
// declaration of non-member friend operator
// if it doesn't need to be a friend, this declaration isn't needed
friend
bool operator<(foo const& lhs, foo const& rhs);
private:
T t;
U u;
V v;
};
bool operator<(foo const& lhs, foo const& rhs)
{
// could be boost::tie
return std::tie(lhs.t, lhs.u, lhs.v) < std::tie(rhs.t, rhs.u, rhs.v);
}
As you can see it's not fully automatic as the implementation of operator< needs to list every member of foo (or at least those that matter for the ordering), twice. There isn't a better way I'm afraid.
Instead of providing an operator< you can specialize std::less for foo but that's a bit exotic and not the preferred way. If the ordering would still not make sense to be part of the extended interface of foo (e.g. there might be more than one ordering that makes sense without a canonical one), then the preferred way is to write a functor:
struct foo_ordering {
bool operator()(foo const& lhs, foo const& rhs) const
{
/* implementation as before, but access control/friendship
has to be planned for just like for operator< */
}
};
Then you'd use e.g. std::set<foo, foo_ordering>.
Be aware that no matter what form the ordering takes (through either operator<, std::less<foo> or a functor) if it is used with an std::set or any other associative container (and by default e.g. std::set<T> uses std::less<T> which in turn uses operator< by default) it must follow some stringent criteria, i.e. it must be a strict weak ordering. However if all the members that are used for the foo ordering themselves have SW orderings then the resulting lexicographical ordering is also a SW ordering.
You have to define a strict ordering of your objects. So if your object is made up of n members a_1 .. a_n which all have a strict ordering themselves, what you can do is:
bool operator< (const TYPE &rhs) {
if (a_1 < rhs.a_1) return true; else if (a_1 > rhs.a_1) return false;
if (a_2 < rhs.a_2) return true; else if (a_2 > rhs.a_2) return false;
...
if (a_n < rhs.a_n) return true;
return false;
}
Edit:
If either boost or C++11 is an option for you, you should really go with the std::tie/boost::tie method Luc Danton suggests in his answer. It's much cleaner.
std::set element comparison function should define Strict Weak Ordering relation on elements domain. Using this definition we can say that two elements are equivalent if compare( a, b ) is false and compare( b, a ) is false too. std::find can be implemented using this assumption.
You can find more here: http://www.sgi.com/tech/stl/set.html and http://www.sgi.com/tech/stl/StrictWeakOrdering.html
Your operator < should be capable to compare every object with given one, like that
struct Data
{
bool operator < (const Data& right) const
{
return( (this.i < right.i) ||
(!(this.i > right.i) && (this.f < right.f)) ||
(!(this.i > right.i) && !(this.f > right.f) && (this.c < right.c)));
}
}
Also, your compare algorithm looks doubtful, because it doees not consider cases, when
this.i == right.i
or
this.f == right.f
And you actually should not be interested in std::set implementation. It can change from compiler to compiler and can be modified in future. Your program should make assumptions only about container interface, never implementation.
This is only a partial answer, but a detailed documentation of STL can be found on the website of SGI.