Em 11/11/2017 , o comitê ISO C ++ adotou a proposta de Herb Sutter para o operador de comparação tripartida <=> "nave espacial" como um dos novos recursos adicionados ao C ++ 20 . No artigo intitulado Comparação consistente Sutter, Maurer e Brown demonstram os conceitos do novo design. Para uma visão geral da proposta, aqui está um trecho do artigo:
A expressão a <=> b retorna um objeto que compara <0 se a <b , compara > 0 se a> b e compara == 0 se a e b são iguais / equivalentes.
Caso comum: para escrever todas as comparações para o seu tipo X com o tipo Y , com semântica de membro, basta escrever:
auto X::operator<=>(const Y&) =default;
Casos avançados: para escrever todas as comparações para o seu tipo X com o tipo Y , basta escrever o operador <=> que usa um Y , pode usar
= default para obter semântica de membro, se desejar, e retornar o tipo de categoria apropriado:
- Retorne um _ordering se seu tipo suportar naturalmente < , e geraremos eficientemente simétricos < , > , <= , > = , == e
! = ; caso contrário, retorne uma _equality e geraremos eficientemente == e ! = simétricos .
- Retorne forte_ se para o seu tipo a == b implica f (a) == f (b) (substituibilidade, onde f lê apenas o estado saliente da comparação que é acessível usando os membros públicos const ), caso contrário, retorne
fraco_ .
Categorias de comparação
Cinco categorias de comparação são definidas como std::tipos, cada um com os seguintes 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 | |
+------------------+------+------------+---------------+-------------+
Conversões implícitas entre esses tipos são definidas da seguinte maneira:
strong_orderingcom valores { less, equal, greater} converte implicitamente:
weak_orderingcom valores { less, equivalent, greater}
partial_orderingcom valores { less, equivalent, greater}
strong_equalitycom valores { unequal, equal, unequal}
weak_equalitycom valores { nonequivalent, equivalent, nonequivalent}
weak_orderingcom valores { less, equivalent, greater} converte implicitamente:
partial_orderingcom valores { less, equivalent, greater}
weak_equalitycom valores { nonequivalent, equivalent, nonequivalent}
partial_orderingcom valores { less, equivalent, greater, unordered} converte implicitamente:
weak_equalitycom valores { nonequivalent, equivalent, nonequivalent, nonequivalent}
strong_equalitycom valores { equal, unequal} converte implicitamente em:
weak_equalitycom valores { equivalent, nonequivalent}
Comparação de três vias
O <=>token é introduzido. A sequência de caracteres <=>simboliza para <= >, no código-fonte antigo. Por exemplo, X<&Y::operator<=>precisa adicionar um espaço para manter seu significado.
O operador sobrecarregável <=>é uma função de comparação de três vias e tem precedência maior que <e menor que <<. Ele retorna um tipo que pode ser comparado com literal, 0mas outros tipos de retorno são permitidos, como suporte a modelos de expressão. Todos os <=>operadores definidos no idioma e na biblioteca padrão retornam um dos 5 std::tipos de categorias de comparação mencionados acima .
Para tipos de idiomas, <=>são fornecidas as seguintes comparações do mesmo tipo internas. Todos são constexpr , exceto onde indicado de outra forma. Essas comparações não podem ser chamadas de forma heterogênea usando promoções / conversões escalares.
- Para
booltipos de integrante e ponteiro, <=>retorna strong_ordering.
- Para tipos de ponteiros, as diferentes qualificações de cv e conversões de derivadas para base podem invocar um built-in homogêneo
<=>e existem heterogêneos embutidos operator<=>(T*, nullptr_t). Somente comparações de ponteiros com o mesmo objeto / alocação são expressões constantes.
- Para tipos de ponto flutuante fundamentais,
<=>retorna partial_orderinge pode ser chamado de forma heterogênea, ampliando argumentos para um tipo de ponto flutuante maior.
- Para enumerações,
<=>retorna o mesmo que o tipo subjacente da enumeração <=>.
- Pois
nullptr_t, <=>retorna strong_orderinge sempre produz equal.
- Para matrizes copiáveis,
T[N] <=> T[N]retorna o mesmo tipo que T's <=>e executa comparação lexicográfica elemento a elemento. Não há <=>para outras matrizes.
- Pois
voidnão há <=>.
Para entender melhor o funcionamento interno deste operador, leia o documento original . Isso é exatamente o que eu descobri usando os mecanismos de pesquisa.