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_ordering
com valores { less
, equal
, greater
} converte implicitamente:
weak_ordering
com valores { less
, equivalent
, greater
}
partial_ordering
com valores { less
, equivalent
, greater
}
strong_equality
com valores { unequal
, equal
, unequal
}
weak_equality
com valores { nonequivalent
, equivalent
, nonequivalent
}
weak_ordering
com valores { less
, equivalent
, greater
} converte implicitamente:
partial_ordering
com valores { less
, equivalent
, greater
}
weak_equality
com valores { nonequivalent
, equivalent
, nonequivalent
}
partial_ordering
com valores { less
, equivalent
, greater
, unordered
} converte implicitamente:
weak_equality
com valores { nonequivalent
, equivalent
, nonequivalent
, nonequivalent
}
strong_equality
com valores { equal
, unequal
} converte implicitamente em:
weak_equality
com 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, 0
mas 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
bool
tipos 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_ordering
e 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_ordering
e 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
void
nã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.