0

I am trying to implement a comparator function, and coming from a JavaScript background attempted to chain them like so:

int MyClass::compare(MyClass & other) {
  return MyClass.x.compare(other.x) || MyClass.y.compare(other.y);
}

That is, compare the objects' x values, and if they are equal compare the objects' y values.

I immediately realized this wouldn't work, because the OR function in c++ returns a bool rather than the last evaluated value.

Other than literally writing an if statement, like

int result = MyClass.x.compare(other.x);
if (result) {
  return result;
}

result = MyClass.y.compare(other.y);
return result;

, is there is a concise way to write this expression?

Moshi
  • 1
  • do you know the `(condition) ? ture_case : false_case` syntax? this can be nested (but better use parenthesis). –  Dec 06 '19 at 06:09
  • why is `compare` returning a value? It doesn't make sense with that name. It should returns -1, 0 or 1 like the [spaceship operator](https://stackoverflow.com/q/49661170/995714). Or use `.equals()` and return a bool – phuclv Dec 06 '19 at 06:12
  • @generic_opto_guy The problem I have is that it would still require some sort of temporary variable in order to avoid recomputation, such as `return (result = my.x.compare(other.x)) ? result : (result = my.y.compare(other.y))` which IMO becomes unreadable after a while and is pretty much the same as the if statement method. – Moshi Dec 06 '19 at 06:15
  • 1
    Confirm or squelch the [XY-problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) inquisition: What is this "compare" being used *for* ? – WhozCraig Dec 06 '19 at 06:16
  • @phuclv In my case, I'm comparing strings with string.compare in order to create an ordering of the class. – Moshi Dec 06 '19 at 06:18
  • @Moshi that's exactly what `std::less` used for in sorting functions. Why don't just use `std::sort`? – phuclv Dec 06 '19 at 06:23
  • @phuclv do you mean something like overloading `operator<`, which is then trivial to chain (`return my.x < other.x || my.y < other.y`)? Though that does help for my situation, I still regularly use this construct in my JavaScript programs and was wondering if there was an equivalent in c++ – Moshi Dec 06 '19 at 07:01
  • no. The fact that you're using it in JS doesn't mean it's logical or makes sense. The correct C++ way is to use `std::sort(strList.begin(), strList.end())` since there are already comparison function for strings. For custom types or comparisons then pass another comparator function. Even if you really want to return one of 2 values then there are `std::max` and `std::min` – phuclv Dec 06 '19 at 07:22
  • @phuclv Perhaps it doesn't make sense for my particular situation, but it still has it's uses. Basically, this is like the null-coalescing operator, but for integral types. Also, std::max and min won't really help, I want the first non zero value, not the maximum or minimum. – Moshi Dec 06 '19 at 07:45
  • 1
    @Moshi short code constructs do not necessarily mean they are better to read and maintain. And the `||` operator in js is just such a thing, in many cases, it seems to be clear for what it is used, e.g. to define a default value. But using it for a default value does not work for every case, so you always need to think about if it is valid to use it in that case, and in a code review you will always need to double-check if the `||` is valid. And as you can't use `||` in every case then those where you don't use `||` might look wrong/off. – t.niese Dec 06 '19 at 10:07

0 Answers0