El 11-11-2017 , el comité ISO C ++ adoptó la propuesta de Herb Sutter para el operador de comparación de tres vías <=> "nave espacial" como una de las nuevas características que se agregaron a C ++ 20 . En el artículo titulado Comparación consistente Sutter, Maurer y Brown demuestran los conceptos del nuevo diseño. Para obtener una descripción general de la propuesta, aquí hay un extracto del artículo:
La expresión a <=> b devuelve un objeto que compara <0 si a <b , compara > 0 si a> b , y compara == 0 si a y b son iguales / equivalentes.
Caso común: para escribir todas las comparaciones para su tipo X con el tipo Y , con la semántica de miembro, simplemente escriba:
auto X::operator<=>(const Y&) =default;
Casos avanzados: para escribir todas las comparaciones para su tipo X con el tipo Y , simplemente escriba el operador <=> que toma una Y , puede usar
= default para obtener la semántica de miembro si lo desea, y devuelve el tipo de categoría apropiado:
- Devuelva una orden si su tipo admite naturalmente < , y generaremos eficientemente < , > , <= , > = , == y
! = ; de lo contrario, devolverá una _equality y generaremos eficientemente simétrica == y ! = .
- Devuelva strong_ si para su tipo a == b implica f (a) == f (b) (sustituibilidad, donde f lee solo el estado relevante de comparación al que se puede acceder utilizando los miembros de const público ), de lo contrario, devuelve
débil_ .
Categorías de comparación
Cinco categorías de comparación se definen como std::
tipos, cada una con los siguientes valores predefinidos:
+--------------------------------------------------------------------+
| | 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 | |
+------------------+------+------------+---------------+-------------+
Las conversiones implícitas entre estos tipos se definen de la siguiente manera:
strong_ordering
con valores { less
, equal
, greater
} convierte implícitamente a:
weak_ordering
con los valores { less
, equivalent
, greater
}
partial_ordering
con los valores { less
, equivalent
, greater
}
strong_equality
con los valores { unequal
, equal
, unequal
}
weak_equality
con los valores { nonequivalent
, equivalent
, nonequivalent
}
weak_ordering
con valores { less
, equivalent
, greater
} convierte implícitamente a:
partial_ordering
con los valores { less
, equivalent
, greater
}
weak_equality
con los valores { nonequivalent
, equivalent
, nonequivalent
}
partial_ordering
con valores { less
, equivalent
, greater
, unordered
} convierte implícitamente a:
weak_equality
con los valores { nonequivalent
, equivalent
, nonequivalent
, nonequivalent
}
strong_equality
con valores { equal
, unequal
} se convierte implícitamente en:
weak_equality
con valores { equivalent
, nonequivalent
}
Comparación de tres vías
Se <=>
introduce el token. La secuencia de caracteres se <=>
tokeniza <= >
en el código fuente anterior. Por ejemplo, X<&Y::operator<=>
necesita agregar un espacio para retener su significado.
El operador sobrecargable <=>
es una función de comparación de tres vías y tiene prioridad mayor que <
y menor que <<
. Devuelve un tipo que se puede comparar con el literal, 0
pero se permiten otros tipos de retorno, como para admitir plantillas de expresión. Todos los <=>
operadores definidos en el idioma y en la biblioteca estándar devuelven uno de los 5 std::
tipos de categorías de comparación mencionados anteriormente .
Para los tipos de idioma, se proporcionan las siguientes <=>
comparaciones integradas del mismo tipo. Todos son constexpr , excepto donde se indique lo contrario. Estas comparaciones no pueden invocarse heterogéneamente usando promociones / conversiones escalares.
- For
bool
, integral y tipos de puntero, <=>
devuelve strong_ordering
.
- Para los tipos de puntero, las diferentes calificaciones de cv y las conversiones derivadas a base pueden invocar una función integrada homogénea
<=>
, y hay funciones heterogéneas integradas operator<=>(T*, nullptr_t)
. Solo las comparaciones de punteros al mismo objeto / asignación son expresiones constantes.
- Para los tipos de coma flotante fundamentales,
<=>
retornos partial_ordering
, y se puede invocar de manera heterogénea ampliando los argumentos a un tipo de coma flotante más grande.
- Para las enumeraciones,
<=>
devuelve lo mismo que los tipos subyacentes de la enumeración <=>
.
- Para
nullptr_t
, <=>
vuelve strong_ordering
y siempre rinde equal
.
- Para matrices copiables,
T[N] <=> T[N]
devuelve el mismo tipo que T
's <=>
y realiza una comparación lexicográfica por elementos. No hay <=>
para otras matrices.
- Por
void
allí no está <=>
.
Para comprender mejor el funcionamiento interno de este operador, lea el documento original . Esto es justo lo que descubrí usando los motores de búsqueda.