Операторы двустороннего сравнения должны быть функциями, не являющимися членами, если:
- вы хотите, чтобы первый операнд имел тип, который не является этим классом
- вы хотите неявный типпреобразование любого из двух операндов
Новый оператор трехстороннего сравнения C ++ 20 имеет правила симметричной генерации.Поиск имени для выражения a@b
, где @
- оператор двустороннего сравнения, выполняется в порядке a@b
, a<=>b
и b<=>a
(с этим порядком предпочтения в случае неоднозначности при выборелучшее совпадение из установленного разрешения перегрузки).Подробнее см. P0515R2 .Это означает, что оператор <=>
может быть функцией-членом и все же разрешать первому операнду не относиться к этому типу класса.
Однако в документе содержится следующее примечание:
Обычно оператор <=> должен быть просто функцией-членом;вы по-прежнему будете получать преобразования для каждого параметра из-за симметричных правил генерации в §2.3.В редком случае, когда вы также хотите поддерживать преобразования по обоим параметрам одновременно (чтобы можно было сравнивать два объекта, ни один из которых не относится к этому типу, но с использованием функции сравнения этого типа), сделайте его другом, не являющимся членом.
Если я правильно понимаю, это говорит о том, что не-членская реализация должна быть необходима, только если требуется неявное преобразование для обоих операндов одновременно?Это верно?Могу ли я увидеть реальный пример, когда это необходимо?Я думаю об этом, хотя это не похоже на действительный пример:
struct foo
{
foo(int const x)
: data{ x } {}
foo(std::string_view x)
: data{std::stoi(x.data())}{}
friend auto operator<=>(foo const & lhv, foo const & rhv) noexcept
{
return lhv.data <=> rhv.data;
}
private:
int data;
};
int main()
{
assert(foo {42} == foo {"42"}); // OK
assert(42 == std::string_view("42")); // ??
}