На 2017-11-11 , Комітет з ISO C ++ прийнятий Herb Sutter пропозиції «s для <=> оператора порівняння триходового" космічного корабля " в якості одного з нових функцій , які були додані в C ++ 20 . У статті під назвою Послідовне порівняння Саттер, Маурер та Браун демонструють концепції нового дизайну. Огляд пропозиції, ось уривок із статті:
Вираз a <=> b повертає об'єкт, який порівнює <0, якщо a <b , порівнює > 0, якщо a> b , і порівнює == 0, якщо a і b рівні / еквівалентні.
Поширений випадок: щоб написати всі порівняння для вашого типу X із типом Y із семантиками, що належать до членів, просто напишіть:
auto X::operator<=>(const Y&) =default;
Розширені випадки. Щоб написати всі порівняння для типу X із типом Y , просто напишіть оператор <=>, який приймає Y , за допомогою цього пункту можна використовувати
= за замовчуванням, щоб отримати семантику членства, і поверне відповідний тип категорії:
- Повертає _ordering , якщо ваш тип природним чином підтримує < , і ми будемо ефективно генерувати симетричний < , > , <= , > = , == і
! = ; інакше повернемо _рівність , і ми будемо ефективно генерувати симетричні == і ! = .
- Повертайтеся strong_, якщо для вашого типу a == b означає f (a) == f (b) (замінюваність, де f читає лише стан порівняння, який доступний за допомогою публічних членів const ), інакше поверніть
слабкий_ .
Порівняльні категорії
П'ять категорій порівняння визначаються як std::
типи, кожна з яких має такі заздалегідь задані значення:
+--------------------------------------------------------------------+
| | Numeric values | Non-numeric |
| Category +-----------------------------------+ |
| | -1 | 0 | +1 | values |
+------------------+------+------------+---------------+-------------+
| strong_ordering | less | equal | greater | |
| weak_ordering | less | equivalent | greater | |
| partial_ordering | less | equivalent | greater | unordered |
| strong_equality | | equal | nonequal | |
| weak_equality | | equivalent | nonequivalent | |
+------------------+------+------------+---------------+-------------+
Неявні перетворення між цими типами визначаються наступним чином:
strong_ordering
зі значеннями { less
, equal
, greater
} неявно перетворює в:
weak_ordering
зі значеннями { less
, equivalent
, greater
}
partial_ordering
зі значеннями { less
, equivalent
, greater
}
strong_equality
зі значеннями { unequal
, equal
, unequal
}
weak_equality
зі значеннями { nonequivalent
, equivalent
, nonequivalent
}
weak_ordering
зі значеннями { less
, equivalent
, greater
} неявно перетворює в:
partial_ordering
зі значеннями { less
, equivalent
, greater
}
weak_equality
зі значеннями { nonequivalent
, equivalent
, nonequivalent
}
partial_ordering
зі значеннями { less
, equivalent
, greater
, unordered
} неявно перетворює в:
weak_equality
зі значеннями { nonequivalent
, equivalent
, nonequivalent
, nonequivalent
}
strong_equality
зі значеннями { equal
, unequal
} неявно перетворюється на:
weak_equality
зі значеннями { equivalent
, nonequivalent
}
Тристороннє порівняння
<=>
Маркер вводиться. Послідовність символів в старому вихідному коді <=>
вказується на <= >
. Наприклад, X<&Y::operator<=>
потрібно додати пробіл, щоб зберегти своє значення.
Оператор, що завантажується, <=>
- це тристороння функція порівняння та має перевагу вище <
та нижче <<
. Він повертає тип, який можна порівняти з буквальним, 0
але допускаються інші типи повернення, такі як підтримка шаблонів виразів. Усі <=>
оператори, визначені мовою та стандартною бібліотекою, повертають один із 5 вищезгаданих std::
типів категорії порівняння.
Для мовних типів <=>
надаються такі вбудовані порівняння одного типу. Усі є constexpr , за винятком випадків, коли зазначено інше. Ці порівняння не можна викликати неоднорідно, використовуючи скалярні рекламні акції / конверсії.
- Для
bool
, інтегральних та вказівних типів, <=>
повертається strong_ordering
.
- Для типів вказівників різним cv-кваліфікаціям та перетворенням на базу дозволяється викликати однорідну вбудовану
<=>
, а є вбудовані гетерогенні operator<=>(T*, nullptr_t)
. Лише порівняння покажчиків на один і той же об'єкт / розподіл є постійними виразами.
- Для основних типів з плаваючою точкою
<=>
повертаються partial_ordering
і можуть бути викликані неоднорідно шляхом розширення аргументів до більшого типу з плаваючою точкою.
- Для перерахувань
<=>
повертає те саме, що і базовий тип перерахування <=>
.
- Для
nullptr_t
, <=>
повернень strong_ordering
і завжди дає equal
.
- Для масивів, що копіюються,
T[N] <=> T[N]
повертає той самий тип, T
що <=>
і s, і виконує лексикографічне порівнювання елементів. Для <=>
інших масивів немає.
- Бо
void
немає <=>
.
Щоб краще зрозуміти внутрішню роботу цього оператора, будь ласка, прочитайте оригінальний документ . Це саме те, що я дізнався за допомогою пошукових систем.