Mientras intentaba aprender sobre los operadores de C ++ , me topé con un extraño operador de comparación en cppreference.com , * en una tabla que se veía así:
"Bueno, si estos son operadores comunes en C ++, será mejor que los aprenda", pensé. Pero todos mis intentos de dilucidar este misterio no tuvieron éxito. Incluso aquí, en Stack Overflow, no tuve suerte en mi búsqueda.
¿Hay alguna conexión entre <=> y C ++ ?
Y si lo hay, ¿qué hace exactamente este operador?
* Mientras tanto, cppreference.com actualizó esa página y ahora contiene información sobre el <=>
operador.
bar< foo::operator<=>
es un ejemplo de cómo podría ser como el<--
operador.Respuestas:
Esto se llama el operador de comparación de tres vías .
De acuerdo con la propuesta de papel P0515 :
La cppreference dice:
fuente
<0
", "compara>0
" y "compara==0
", significan que<=>
devuelve un valor negativo, positivo o cero, según los argumentos. Al igual questrncmp
ymemcmp
.'a' < 'a'
y ambos'c' < 'a'
son falsos,'a' < 'a'
y'a' < 'c'
no lo son. EN ORDENAMIENTO SIGUIENTE lo siguiente es cierto:a != b
→a < b || b < a
operator==(T x, T y) { return !(x < y) && !(y < x); }
yoperator!=(T x, T y) { return (x < y) || (y < x); }
- ¡ah-ha! Por supuesto, esto es menos eficiente que un verdadero,==
ya que invoca la comparación dos veces, pero sigue siendo ordenado.< 0
evalúa como verdadero. Es decir, sia < b
entonces(a <=> b) < 0
siempre es cierto.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:
Categorías de comparación
Cinco categorías de comparación se definen como
std::
tipos, cada una con los siguientes valores predefinidos: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 5std::
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.bool
, integral y tipos de puntero,<=>
devuelvestrong_ordering
.<=>
, y hay funciones heterogéneas integradasoperator<=>(T*, nullptr_t)
. Solo las comparaciones de punteros al mismo objeto / asignación son expresiones constantes.<=>
retornospartial_ordering
, y se puede invocar de manera heterogénea ampliando los argumentos a un tipo de coma flotante más grande.<=>
devuelve lo mismo que los tipos subyacentes de la enumeración<=>
.nullptr_t
,<=>
vuelvestrong_ordering
y siempre rindeequal
.T[N] <=> T[N]
devuelve el mismo tipo queT
's<=>
y realiza una comparación lexicográfica por elementos. No hay<=>
para otras matrices.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.
fuente
_equality
tipos murieron: resultó que funciona<=>
bien con los cuatro operadores relacionales pero no tan bien con los dos operadores de igualdad (aunque hay algo de azúcar sintáctica intensa para respaldar el caso común donde los quiere a todos).Esta respuesta se ha vuelto irrelevante desde que la página web referenciada ha cambiado
La página web a la que hace referencia estaba rota. Se estaba editando mucho ese día y las diferentes partes no estaban sincronizadas. El estado cuando lo miraba era:
En la parte superior de la página, enumera los operadores de comparación existentes actualmente (en C ++ 14). No hay
<=>
ahi.En la parte inferior de la página, deberían haber enumerado los mismos operadores, pero se burlaron y agregaron esta sugerencia futura.
gcc
aún no lo sabe<=>
(y con-std=c++14
, nunca lo sabrá), por lo que cree que lo quiso decira <= > b
. Esto explica el mensaje de error.Si intenta lo mismo dentro de cinco años, probablemente obtendrá un mejor mensaje de error, algo como
<=> not part of C++14.
fuente
<=>
operador con la etiqueta (desde C ++ 20), que le indica en qué versión del estándar debe esperar. El etiquetado de estándares es una convención que sigue cppreference.com. Por supuesto, no tiene un compilador que regresó en una máquina del tiempo para admitirlo, pero cpprefernce le dice (correctamente) qué esperar.