10

I need to be able to compare one of my classes (which contains a lot more than an integer) to integers, even though that might be stretching the like of equality a little it's close enough...

How do I overload the equality operator for different types?

I basically have a class like this

struct MyClass {
    int start;
    int middle;
    int threequarters;
};

and the overloaded operator

inline bool operator==(const MyClass& lhs, const MyClass& rhs) {
    return lhs.middle == rhs.middle;
}

So when comparing with integers I need to compare against the middle variable as well, but I'm not sure if I need two sets of operator functions, one where integer is lhs and one where integer is rhs?

inline bool operator==(const int& lhs, const MyClass& rhs) {
    return lhs == rhs.middle;
}

inline bool operator==(const MyClass& lhs, const int& rhs) {
    return lhs.middle == rhs;
}
5
  • 1
    Yes, you should do it that way - support (int,MyClass) and (MyClass,int). Although you can define one of the operators in terms of the other. Another possibility is to have a constructor for MyClass which constructs from an int - then you'll only need an operator(MyClass,MyClass) because when the compiler encounters the int it can promote it to be type MyClass for the operator. Commented Apr 17, 2014 at 20:29
  • So to compare MyClass with MyClass, and integers with MyClass, I'll need 3 sets of every comparison function (18 in total), even though most of them will reference others..? Commented Apr 17, 2014 at 20:31
  • 2
    Or give your class a converting constructor MyClass(int i) : middle(i) {}. Commented Apr 17, 2014 at 20:32
  • Overloading the comparison operator so that it doesn't compare all parts of the object seems like bad practice to me. If you want a function like this I would prefer to just define a function with a name that describes what it does, something like bool areEqualAtMiddle(const MyClass& lhs, const MyClass& rhs) Commented Apr 17, 2014 at 20:43
  • @ChrisDrew Yes I know, it's just that I store these MyClass in a set and at some points during the execution I only have access to the middle value, so I need to get the reference back somehow... Commented Apr 17, 2014 at 20:48

3 Answers 3

9

To clarify from my comment, this will support code so you can either provide all variations of operators:

inline bool operator==(const MyClass& lhs, const MyClass& rhs) {
return lhs.middle == rhs.middle;
}

inline bool operator==(const int& lhs, const MyClass& rhs) {
return lhs == rhs.middle;
}

inline bool operator==(const MyClass& lhs, const int& rhs) {
return lhs.middle == rhs;
}

And do that for every operator (which blows up into a significant amount of code). OR if it makes sense to, you can provide a constructor which constructs from int:

struct MyClass {
MyClass() {} // default
MyClass( int x ) { /* init for an int here */ }
int start;
int middle;
int threequarters;
};

If you do this, then you will only need the MyClass,MyClass version for each operator:

inline bool operator==(const MyClass& lhs, const MyClass& rhs) {
return lhs.middle == rhs.middle;
}

Because when the compiler sees:

if ( 5 == my_class ) {}

It actually does this:

if ( MyClass(5).operator==( my_class ) ) {}
Sign up to request clarification or add additional context in comments.

1 Comment

C++ Core Guidelines C.86 discourages from declaring implicit single-argument constructors. It's not an absolute but you have to be aware of the pitfalls and surprises that can happen if you add it.
1

Yes, you need to define three operator == provided that your class has no conversion constructor for objects of type int.

inline bool operator==(const MyClass& lhs, const MyClass& rhs) {
    return lhs.middle == rhs.middle;
}

inline bool operator==(const MyClass& lhs, int rhs) {
    return lhs.middle == rhs;
}

inline bool operator==(int lhs, const MyClass& rhs) {
    return operator ==( rhs, lhs );
}

2 Comments

And I shouldn't ... const int& rhs ...?
@user3235200 No there is no any need to use const int &. it is enough and better to use int.
0

Yes, you need both operators.

bool operator==(const A& a, const int & b)
{
    return a.value == b;
};

With only the above operator defined, the compiler will throw an error that no conversion is available if you try the following: 2 == a (considering that the class A has no implicit constructors that take an integer as an argument)

For each binary operation, the compiler tries to do an implicit conversion to fit the operation. For instance, if class A had an operator int definition, you would not need the operators, since the compiler would implicitly convert the A type to an integer and then perform the bool operator==(int,int) operation. If no operator is defined, then the compiler throws an error, saying that there is no conversion available (i.e, no operator == that accepts A as an argument on either left or right side)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.