Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Real world usage example for spaceship operator [closed]

The definition of spaceship operator is meant to have a strong definition of ordering, but does this affect the way your client code is written or just how to define your class comparison operators?

Since in other post are missing real world example I'm not fully understanding this part.

Other SO post about spaceship operator:

  • Why do we need the spaceship <=> operator in C++?
  • What is the <=> operator in C++? https://stackoverflow.com/questions/47485803/how-and-why-did-the-iso-c-standards-committee-wg21-decide-to-accept-the-prop
  • How is the three-way comparison operator different from subtraction?
like image 612
Moia Avatar asked Jan 23 '19 11:01

Moia


People also ask

What is spaceship operator used for?

In PHP 7, a new feature, spaceship operator has been introduced. It is used to compare two expressions. It returns -1, 0 or 1 when first expression is respectively less than, equal to, or greater than second expression.

What does <=> mean in Ruby?

It's a general comparison operator. It returns either a -1, 0, or +1 depending on whether its receiver is less than, equal to, or greater than its argument.

How do I use the spaceship operator?

You can directly use the spaceship operator for int 's (1), for string 's (2), and for vecto r's (3). Thanks to the wandbox online-compiler and the newest GCC, here is the output of the program.

Does the spaceship operator always perform a lexicographic comparison?

Some very smart people on the standardization committee noticed that the spaceship operator will always perform a lexicographic comparison of elements no matter what. Unconditionally performing lexicographic comparisons can lead to inefficient generated code with the equality operator in particular. The canonical example is comparing two strings.

How to do a three-way comparison using spaceship operator?

The spaceship operator determines for two objects A and B whether A < B, A = B, or A > B. The spaceship operator or the compiler can auto-generate it for us. Also, a three-way comparison is a function that will give the entire relationship in one query. Traditionally, strcmp () is such a function. Given two strings it will return an integer where,

Can spaceship operator be rewritten in c++20?

Let’s explore the answer to this question. In C++20, the compiler is introduced to a new concept referred to “rewritten” expressions. The spaceship operator, along with operator==, are among the first two candidates subject to rewritten expressions.


2 Answers

You just compare the way you've always done:

a < b

It's just that under the hood, one of the candidate functions for that expression will also find (a <=> b) < 0 and if that candidate exists and happens to be the best viable candidate, then it is invoked.

You typically don't use <=> directly in "client code", you just use the comparisons that you want directly.

For instance, given:

struct X {
    int i;

    // this can be = default, just writing it out for clarity
    strong_ordering operator<=>(X const& rhs) const { return i <=> rhs.i; }
};

The expression

X{42} < X{57};

will evaluate as X{42} <=> X{57} < 0 (there is no < candidate, so <=> non-reversed is trivially the best candidate). X{42} <=> X{57} evaluates as 42 <=> 57 which is strong_ordering::less. And that < 0 returns true. Hence, the initial expression is true... as expected.

The same operator also directly gives us that X{57} > X{42}, that X{3} >= X{2}, etc.


The advantage of <=> is that you only need to write one operator instead of four, that operator is typically much easier to write than <, you can properly express the differentiation between partial and total orders, and stacking it is typically more performant (e.g. in the cases like string).

Additionally, we don't have to live in this weird world where everyone pretends that operator< is the only relational operator that exists.

like image 180
Barry Avatar answered Oct 13 '22 13:10

Barry


<=> allows the lazy way to also be the performant way. You don't change your client code.

Clients may see performance benefits when there was a using std::rel_ops (or boost::ordered etc).

An example

// old and busted
struct Person : boost::totally_ordered<Person>
{
    std::string firstname;
    std::string lastname
    bool operator<(const Person & other) 
    { 
        return std::tie(firstname, lastname)
             < std::tie(other.firstname, other.lastname); 
    }
}

// new hotness
struct Person
{
    std::string firstname;
    std::string lastname;
    auto operator<=>(const Person &) = default;
}

int main()
{
    Person person1 { "John", "Smith" };
    Person person2 { "John", "Smith" };
    std::cout << person2 <= person1 << std::endl;
}
like image 4
Caleth Avatar answered Oct 13 '22 12:10

Caleth