Рассмотрите этот код:
#include <iostream>
#include <compare>
class A {
public:
int i = {};
std::strong_ordering operator<=> (A const& r) const
{
return i <=> r.i;
}
};
void TestA()
{
A a;
A b;
std::cout<< (a<b);
std::cout<< (a>b);
std::cout<< (a<=b);
std::cout<< (a>=b);
//std::cout<< (a==b); //ERROR
std::cout << 'E';
//std::cout<< (a!=b); //ERROR
std::cout << 'E';
std::cout<< std::is_eq(a<=>b);
std::cout<< std::is_neq(a<=>b) << std::endl;
}
class B {
public:
int i = {};
std::strong_ordering operator<=> (B const& r) const = default;
};
void TestB()
{
B a;
B b;
std::cout<< (a<b);
std::cout<< (a>b);
std::cout<< (a<=b);
std::cout<< (a>=b);
std::cout<< (a==b);
std::cout<< (a!=b);
std::cout<< std::is_eq(a<=>b);
std::cout<< std::is_neq(a<=>b) << std::endl;
}
class C {
public:
bool b = {};
int v1 = {};
int v2 = {};
std::strong_ordering operator<=> (C const& r) const
{
return (b?v1:v2) <=> (r.b?r.v1:r.v2);
}
bool operator== (C const& r) const
{
return std::is_eq(*this<=>r);
}
};
void TestC()
{
C a;
C b;
std::cout<< (a<b);
std::cout<< (a>b);
std::cout<< (a<=b);
std::cout<< (a>=b);
std::cout<< (a==b);
std::cout<< (a!=b);
std::cout<< std::is_eq(a<=>b);
std::cout<< std::is_neq(a<=>b) << std::endl;
}
int main()
{
TestA();
TestB();
TestC();
return 0;
}
https://wandbox.org/permlink/SLmLZOc18RaJV7Mu
Удалите комментарии, чтобы получить ошибку.
Сначала я хочу спросить, почему трехсторонний оператор по умолчанию ведет себя иначе, чем пользовательский оператор определения?
И второе, является ли решение этой проблемы правильным для класса C
или оно должно обрабатываться по-другому?
Это просто простой пример, и я имею в виду более сложную ситуацию с десятками полей и союзов (Если вы не знаете, что я имею в виду, посмотрите некоторые API-интерфейсы Intel;)).
Редактировать:
Этот вопрос Оператор равенства не определен для реализации пользовательского оператора космического корабля в C ++ 20 , сфокусированный на том, почему не существует оператора равенства по умолчанию для определяемого пользователем 3-стороннего оператора. Я хотел бы знать, почему существует разница по умолчанию и поведение, определяемое пользователем?
Редактировать 2:
Я немного изменил класс C
в примере, чтобы представить больше реальной проблемы (когда операторы по умолчанию не являются допустимым решением ). Я также хочу уточнить, что я хотел бы знать причины этих различий (между определением пользователя и оператором по умолчанию), чтобы иметь возможность оценить, является ли мое реальное решение правильным (аналогично C
), поскольку я ценю больше поддерживаемости кода чем производительность для части кода, над которым я сейчас работаю.