Reputation: 2137
In g++ 10, I am trying to use three way comparison, just for experiment.
I read that other operators do not needed anymore (except ==).
But even if I can use operator (it is implemented on the compiler), it does not supersede (or imply) !=.
So, the following code does not work.
#include<iostream>
using namespace std;
struct A
{
struct Iterator
{
size_t index;
size_t operator*() { return index + 1000; }
//bool operator!=(const Iterator &a) const { return index != a.index; }
auto operator<=>(const Iterator &a) const { return index <=> a.index; }
Iterator &operator++() { ++index; return *this; }
};
Iterator begin() { return Iterator{0}; }
Iterator end() { return Iterator{5}; }
};
int main()
{
A a;
auto result = a.begin() <=> a.end();
for (auto b : a)
cout << b << "\n";
cout << (a.begin() != a.end()) << "\n";
return 0;
}
What am I missing here?
Upvotes: 4
Views: 1718
Reputation: 550
From cppreference:
In brief, a class that defines
operator<=>
automatically gets compiler-generated operators <, <=, >, and >=. A class can defineoperator<=>
as defaulted, in which case the compiler will also generate the code for that operator."
The code for != and == is not generated, thus you do need to implement the comparisons.
Upvotes: 2
Reputation: 303057
I read that other operators do not needed anymore (except ==).
Right, except ==
is the key bit. There are two categories of comparison operators:
==
, !=
)<=>
, <
, >
, <=
, >=
)In each of those categories, the first one I listed (==
and <=>
) is the primary comparison operator. It is the only operator that you need to define if you want to opt in to that category. If you want equality, provide ==
. If you want ordering, provide <=>
(and also ==
). The other comparison operators are secondary comparison operators - expressions using secondary comparison are, in C++20, rewritten to use the primary comparison operator.
These categories are completely distinct† - there is no crossover. A x != y
expression can invoke operator==(x, y)
or even operator==(y, x)
but it will never invoke an operator<=>
of any kind.
You have code that requires an equality comparison but don't have the equality operator defined, hence it's ill-formed. To get this to work, you need to add:
bool operator==(const Iterator &a) const { return index == a.index; }
auto operator<=>(const Iterator &a) const { return index <=> a.index; }
Note ==
, not !=
. You should not declare secondary comparison operators in C++20, unless you have a very specific need for them (and this is not such a need).
For more, see Comparisons in C++20.
†The single exception to this rule is, for convenience, if you default operator<=>
then you also get a declared, defaulted operator==
. It's as if you had defaulted both yourself. In this example, since your comparisons are just the default member-wise comparisons, you could have written:
auto operator<=>(const Iterator &a) const = default;
As your single comparison operator declaration, which would've behaved as if you'd written:
bool operator==(const Iterator &a) const = default;
auto operator<=>(const Iterator &a) const = default;
Which gives you the correct equality operator you need for your program.
Upvotes: 9
Reputation: 18051
operator ==
is implicitly declared as defaulted for each operator operator <=>
defined as defaulted:
#include<iostream>
using namespace std;
struct A
{
struct Iterator
{
size_t index;
size_t operator*() { return index + 1000; }
//bool operator!=(const Iterator &a) const { return index != a.index; }
auto operator<=>(const Iterator &) const = default;
// bool operator == (const Iterator&) const; implicitly declared
Iterator &operator++() { ++index; return *this; }
};
Iterator begin() { return Iterator{0}; }
Iterator end() { return Iterator{5}; }
};
int main()
{
A a;
auto result = a.begin() <=> a.end();
for (auto b : a)
cout << b << "\n";
cout << (a.begin() != a.end()) << "\n";
return 0;
}
Upvotes: 1