1

As pointed out by this article, it is impossible to overload the comparison operator (==) such that both sides could take primitive types.

"No, the C++ language requires that your operator overloads take at least one operand of a "class type" or enumeration type. The C++ language will not let you define an operator all of whose operands / parameters are of primitive types." (parashift)

I was wondering:

**If I really-really needed to compare two primitives in a non-standard way using the ==, is there a way to implicitly cast them to some other class?

For example, the following code will work for const char* comparison, but it requires an explicit cast. I would prefer to avoid explicit casts if possible.

// With an explicit cast
if(string("a")=="A") // True

// Without the cast
if("a"=="A") // False

// An example overloaded function:
bool operator == (string a, const char* b)
{
    // Compares ignoring case
}

Casting can be pretty clunky in some situations, especially if you need to do several casts inside a long expression. So that's why I was looking for a way to automatically cast the first input (or both) to a sting type.


Edit 1:

Another way to do this is to write an isEqual(const char* a, const char* b) function, but I want to avoid this because it will result in a mess of parenthesis if I were to use it inside of a large if-statement. Here's an oversimplified example that still shows what I mean:

if (str1 == str2 || str1 == str3 || str2==str4)

As opposed to:

if (isEqual(str1,str2) || isEqual(str1,str3) || isEqual(str2,str4))


Edit 2:

I know there exist many ways to achieve the desired functionality without overloading the ==. But I looking specifically for a way to make the == work because I then could apply the knowledge to other operators as well.

This question is in fact closely related to the Wacky Math Calculator question I asked a few weeks ago, and being able to overload the == will help make the code look considerably nicer (visually, but perhaps not in a "clean code" way).

And that's I wanted to ask this question here on SO, in case someone had a cool C++ trick up their sleeve that I didn't know about. But if the answer is No then that's fine too.

Community
  • 1
  • 1
Vladimir
  • 225
  • 1
  • 11
  • 5
    Write a comparison function that takes two arguments of type `const char*`. You don't **have** to use `==` do you now? – Brian Bi Aug 19 '14 at 21:46
  • 2
    Don't (try to) do that, write an explicit function `bool MyEquals(T val1, T val2)` – quantdev Aug 19 '14 at 21:46
  • 1
    A comparison is just a function call with a "special" syntax, so you just write a custom function for comparison. Some containers and algorithms from the STL do this by taking an optional comparison functor, in case you are messing with those. – Ulrich Eckhardt Aug 19 '14 at 21:47
  • How should the code decide when == is using your special form or the original form? – Neil Kirk Aug 19 '14 at 21:49
  • Yes, writing an explicit function will do the trick, but I would prefer just being able to use the == operator as this avoid a mess of parenthesis and help make the code a lot cleaner. – Vladimir Aug 19 '14 at 21:51
  • @NeilKirk, great question! In my case, I actually don't want it to do the original at all. So it will always used the overloaded function. – Vladimir Aug 19 '14 at 21:52
  • Can someone please explain the down vote so I can correct the issue. – Vladimir Aug 19 '14 at 22:01
  • You don't want to create a helper class to help with the job, you don't want to create a free function. You are not leaving yourself much of a choice, are you? – R Sahu Aug 19 '14 at 22:05
  • "help make the code a lot cleaner" - NO! The complete opposite is true - your code will become far less readable and more confusing. Anyone reading the code will expect `==` to behave in the standard way. Conversely, using a `isEqual` function tells the reader immediately that they have to look at the function's documentation to tell what comparison criterion is being used. I suggest you have a look at [this answer](http://stackoverflow.com/a/4421708/1227469) which explains why you should try to avoid operator overloading where you are changing the operator's well-known semantics. – JBentley Aug 19 '14 at 22:11
  • I don't see the problem with the `if ( isEqual(...` version. Especially if you're in an editor with syntax highlighting. – M.M Aug 19 '14 at 22:11
  • @RSahu, You're absolutely right. That's why I wanted to ask on SO, because maybe someone out there has an unusual idea that they could suggest. – Vladimir Aug 19 '14 at 22:11
  • @JBentley, Good point. I was thinking clear in terms of "shorter and nicer looking". But you bring up a good point that it can be more confusing to other programmers. – Vladimir Aug 19 '14 at 22:14
  • @MattMcNabb, Your right, there might not be too much difference. But using the == just looks so much nicer and less confusing -- at least to my eyes. When I see a stack of parenthesis more than 3 layers deep, I just can't make any heads or tails of it. Plus, == allows me to do some pretty cool things with order of operations. – Vladimir Aug 19 '14 at 22:35

3 Answers3

2

You could certainly write one or more free functions to do your comparison. It doesn't have to be an operator overload.

for example:

bool IsEqual(const char* a, const string& b)
{
  // code
}

bool IsEqual(const string& a, const char* b)
{
  // code
}

and so on.

Logicrat
  • 4,438
  • 16
  • 22
  • Thanks Logicrat! This would definitely work, but I would prefer to overload the == because this will avoid a mess of parenthesis when I need to used the function multiple times inside in a single line of code. – Vladimir Aug 19 '14 at 21:55
  • You could do an overload involving `string`, since it is not a basic type. – Logicrat Aug 19 '14 at 22:00
  • @Logicrat, True, but then things like `if("word"=="door")` would still perform pointer comparison instead of my custom comparison. – Vladimir Aug 19 '14 at 22:07
  • 1
    @Vladimir This is just a weakness of C++ you have to live with. – Neil Kirk Aug 19 '14 at 22:08
  • @Logicrat: Except that it _already_ has an `operator==`, and per the One Definition Rule you can't add a second. – MSalters Aug 19 '14 at 22:11
  • @NeilKirk, I agree. I was just wondering if someone had nifty trick up their sleeve that I didn't know about. :) – Vladimir Aug 19 '14 at 22:16
  • 1
    Defining `operator==` as a free function works OK, but I agree there are inherent dangers. If I were to do something like that, I would keep it file-local. – Logicrat Aug 19 '14 at 22:29
  • @Logicrat About your last comment: Do you mean I can define a local `operator==` function that will take primitives? Because I think this is what I was trying to do, albeit unsuccessfully. – Vladimir Aug 19 '14 at 22:43
1

If the types of the operands are given, and you cannot add an overload for equality, because

  • It is simply not overloadable, because all are primitive types
  • There is already an overload, which does not do what you want
  • You do not want to risk violation of the ODR because someone else could be pulling the same kind of stunts you do (In which case a TU-local override might work, aka free file-local. Be aware of adverse effects on templates.)

there are just two options:

  • Use a wrapper and overload all the operators to your hearts content.
  • Use a function having the desired behavior explicitly and just forget about the syntax-sugar.

BTW: That standard-library containers and algorithms often can be customized three ways:

  • Using a type having overloaded operators
  • Having the used standard traits-class specialized
  • Providing a different traits-class.
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
0

No, there's no way to implicitly cast the primitive types the way you want.

The only way to achieve the desired functionality is either by explicitly casting the inputs into another class as stated in the question, or by creating a free function as shown by @Logicat.

Vladimir
  • 225
  • 1
  • 11