25

Why do we need such an operator in C++ and how is it useful in modern C++ programming? Any real world code examples where this can be applied will help.

This question is geared to understand the practical application in real world without reading wordy proposal from Herb Sutter. No offense to the proposal though.

usr
  • 168,620
  • 35
  • 240
  • 369
Ram
  • 3,045
  • 3
  • 27
  • 42
  • Possible duplicate of [Is the three-way comparison operator always efficient?](https://stackoverflow.com/questions/48065905/is-the-three-way-comparison-operator-always-efficient) – t0mm13b Apr 04 '18 at 22:09
  • https://stackoverflow.com/questions/47485803/how-and-why-did-the-iso-c-standards-committee-wg21-decide-to-accept-the-prop – M.M Apr 05 '18 at 02:06
  • 2
    Possible duplicate of [What is the <=> operator in C++?](https://stackoverflow.com/questions/47466358/what-is-the-operator-in-c) – Cris Luengo Jun 15 '18 at 01:07

1 Answers1

21

I'll give you three points of motivation, just off the top of my head:

  1. It's the common generalization of all other comparison operator (for totally-ordered domains): >, >=, ==, <=, < . Using <=> (spaceship), you can implement each of these other operations in a completely generic way.
  2. For strings, it's equivalent to the good old strcmp() function from the C standard library. So - useful for lexicographic order checks, such as data in vectors or lists or other ordered containers.
  3. For integral numbers, it's what the hardware does anyway: On x86 or x86_64 Comparing a and b (CMP RAX, RBX) is basically like subtracting (SUB RAX, RBX) except that RAX doesn't actually change, only the flags are affected, so you can use "jump on equal/not equal/greater than/lesser than/etc." (JE/JNE/JGT/JLT etc.) as the next instruction. CMP should be thought of as a "spaceship compare".
einpoklum
  • 118,144
  • 57
  • 340
  • 684
  • Yeah, but why add an operator and complicate the grammar - which is already an unparseable mess as it is? Just create a `std::compare` working in a similar way as `std::hash` - already provided for builtin types, user definable for custom types. – Matteo Italia Apr 04 '18 at 22:41
  • 5
    @MatteoItalia: 1. It doesn't complicate parsing the grammar. The C++ grammar has a ambiguity issues, this isn't one of them. 2. This is part of a grander scheme of things which will include compiler-generated [default comparison operators](http://en.cppreference.com/w/cpp/language/default_comparisons) for most types, which will be _awesome_. – einpoklum Apr 04 '18 at 22:44
  • Also, point 3 is a bit of a moot point - current compilers already optimize without problems sequences of comparisons regarding the same values. – Matteo Italia Apr 04 '18 at 22:44
  • 2
    @MatteoItalia: about point 3 - not moot, in the same sense that you don't need >= since you have > and =. If the hardware does >=, why shouldn't you be able to say that? – einpoklum Apr 04 '18 at 22:46
  • 1. It's extra syntax, it complicates the grammar. If it can be done without any particular problem with existing syntax, generally you don't want to touch it. 2. So what? Range-based `for` already knows about `begin` and `end`, what would be the problem in letting compiler-generated operators know about `compare`? – Matteo Italia Apr 04 '18 at 22:50
  • You got it reversed. You don't have `<=` because the hardware knows how to do `<=`, you have `<=` because it's an operator that often comes useful when writing code. The compiler then maps it on the underlying hardware the best it can. – Matteo Italia Apr 04 '18 at 22:52
  • 3
    @MatteoItalia: C++ did not invent the 3-way comparison spaceship operator. Other languages did. C++ is merely adopting it in a C++ form. There's no reason for C++ to spell it `compare` when we can just spell it the way everyone else does. – Nicol Bolas Apr 04 '18 at 22:56
  • 1
    @MatteoItalia: "*what would be the problem in letting compiler-generated operators know about compare?*" There's a huge difference between range-based `for` doing ADL lookup on `begin` and canonizing a name (which is common enough to already be in use by many other people) with an `= default` implementation and special language meaning. I'll take the minor grammar "complication" of <=> over breaking tons of code by potentially changing the meaning of every `compare` function that someone has written. – Nicol Bolas Apr 04 '18 at 22:58
  • @NicolBolas: disputable; Python calls it `cmp`; OCaml and Haskell call it `compare`; Java calls it `compareTo`. But ok, it's an operator because someone liked how it looked, not because there's some technical reason why it couldn't be implemented otherwise. That's the answer I was looking for. – Matteo Italia Apr 04 '18 at 23:02
  • 2
    @MatteoItalia: "*it's an operator because someone liked how it looked, not because there's some technical reason why it couldn't be implemented otherwise*" If you wish to pretend that's the case, you can do so. It doesn't make what I said about existing `compare` functions any less true. `operator<=>` has the advantage of having no existing functions to conflict with. – Nicol Bolas Apr 04 '18 at 23:04
  • @NicolBolas: with this kind of reasoning we'd need a new operator for any customization point; I don't expect `compare` to be any more common than - say - `hash`. But you could call it any other way - say, `three_way_compare`; or just ignore ADL and require a template specialization straight into `std` (which would solve the conflict problem once for all). Again, the point is, it's not like it couldn't be done without a grammar modification, it just looks better this way. I'm fine with it, I'm just trying to understand the rationale. – Matteo Italia Apr 04 '18 at 23:08
  • @MatteoItalia: 1. (About your earlier comment regarding hardware capabilities) Sometimes hardware capabilities inspire programming language structures, sometimes it's the other way around. 2. I disagree that if something can be done with existing syntax, you generally don't want to touch it. It's not that the current syntax of C++ is held to be pure and perfect. It's kind of a work-in-progress. Some stuff gets added, occasionally a few things get removed. – einpoklum Apr 05 '18 at 09:12
  • @einpoklum: I'm quite sure that the spaceship operators doesn't arise out of hardware capabilities; it comes out from the need of compactly provide an all-in-one comparison function, and the `<=>` syntax and name actually comes from Perl, which is definitely as far away from hardware as a language can be. Also, intrinsics - which are arguably the part of C and C++ implementations that is nearest to the hardware - are normally provided as functions or function-like macros; operators are just syntactic sugar. – Matteo Italia Apr 05 '18 at 12:03
  • As for the "don't touch the core language if it's not necessary" part, it's just that it's the general attitude used so far in the development of the C++ language, and for a good reason; introducing syntax (and in general, modifications to the core language) is way more cumbersome than adding parts of the library. It breaks compatibility (I'll have to add `#ifdef` in class libraries around `operator<=>`, and the implementation will need to avoid it anyway), it is more difficult to test in existing implementations, it's impossible to backport. Library-only changes are more convenient. – Matteo Italia Apr 05 '18 at 12:09
  • 1
    @MatteoItalia: I feel your pain... Remember, though, that my answer gave potential motivation that springs to my mind, not the choices of the standards committee. – einpoklum Apr 05 '18 at 13:23
  • 3
    @MatteoItalia: "*Library-only changes are more convenient.*" And yet less useful. Without any core language changes, `= default` comparison generation would not be possible. And without *that*, then the ability to put user-defined types in template parameters (something that is being added for C++20) would not be possible. This is no different from rvalue references; you *could* have made that some kind of standard library type that language features could key off of, but then we wouldn't be able to use it to fix forwarding. – Nicol Bolas Apr 08 '18 at 22:37
  • 1
    Why would it not be possible to have user-defined types in template parameters without compiler-generated comparisons? Don't you mean it would be problematic? – einpoklum Apr 08 '18 at 22:42
  • @Moia: I respectfully disagree, as does OP. – einpoklum Jan 23 '19 at 11:32
  • @einpoklum sorry, I meant code example not explanation – Moia Jan 23 '19 at 11:33
  • @MatteoItalia I think it would be cool to have a `hash` operator. Just like Nim enables sigil as function names. you could say `#var` to mean `std::hash(var)` and `<-var` to say `std::move(var)`. These are all liberties you can take in Nim. (or almost; because sigils are actually quite limited) – v.oddou Mar 19 '19 at 10:10