Por que foi introduzido std :: ranges :: less?

Aug 15 2020

Em cppreferência diantestd::ranges::less , nas notas podemos ver que:

Ao contrário std::less, std::ranges::lessexige que todos os seis operadores de comparação <, <=, >, >=, ==e !=de ser válida (através da totally_ordered_withrestrição).

Mas por que? Por que usaríamos em std::ranges::less{}vez de std::less{}? Qual é a situação prática em que queremos less{}apenas se houver outros operadores de comparação definidos, não apenas <aquele?

Respostas

5 NicolBolas Aug 15 2020 at 12:13

Qual é a situação prática em que queremos menos {} apenas se houver outros operadores de comparação definidos, não apenas o <?

Nem tudo na biblioteca Ranges é baseado puramente no que é "prático". Muito disso é sobre como fazer a linguagem e a biblioteca fazerem sentido lógico.

Os conceitos como um recurso de linguagem fornecem à biblioteca padrão a oportunidade de definir combinações significativas de recursos de objeto. Dizer que um tipo tem um operator<é útil do ponto de vista puramente prático de dizer quais operações estão disponíveis para ele. Mas isso realmente não diz nada significativo sobre o tipo.

Se um tipo for totalmente ordenado, isso logicamente significa que você pode usar qualquer um dos operadores de comparação para comparar dois objetos desse tipo. Sob a ideia de uma ordem total, a < be b > asão declarações equivalentes. Portanto, faz sentido que, se o código for restrito a tipos que fornecem uma ordem total, esse código deve ter permissão para usar qualquer uma das instruções.

ranges::less::operator()não usa nenhum operador diferente de <. Mas essa função é restrita a tipos que modelam o totally_orderedconceito. Essa restrição existe porque ranges::lessé para isso : comparar tipos totalmente ordenados. Poderia ter uma restrição mais estreita, mas isso seria jogar fora qualquer significado fornecido pela ordenação total.

Também evita que você exponha detalhes de implementação arbitrários aos usuários. Por exemplo, digamos que você tenha um modelo que aceita algum tipo Te deseja usar Tem uma ranges::lessoperação baseada em. Se você restringir este modelo para apenas ter um operator<, então você efetivamente colocou sua implementação na restrição. Você não tem mais a liberdade de alternar para a implementação ranges::greaterinternamente. Ao passo que, se você tivesse colocado std::totally_orderedsua restrição, deixaria claro para o usuário o que ele precisa fazer, ao mesmo tempo em que se dá a liberdade de usar quaisquer functores de que precisar.

E como operator<=>existe e facilita a implementação dos operadores de pedidos em uma função, não há desvantagens práticas . Bem, exceto para o código que precisa ser compilado em C ++ 17 e C ++ 20.

Essencialmente, você não deve escrever tipos que são "ordenados" apenas operator<para começar.

1 Kyle Aug 15 2020 at 09:20

Até onde posso dizer com base na proposta, a ideia é apenas simplificar o design dos objetos de função. std::lessé uma classe de modelo que requer um parâmetro de modelo e representa uma comparação homogênea. Este parâmetro do modelo pode ser omitido para o padrão, o std::less<void>que permite comparações heterogêneas. O argumento parece ser que o caso homogêneo é desnecessário, já que é bem tratado pela abordagem heterogênea, de modo que o design pode ser consideravelmente simplificado e um modelo de classe não é necessário.

operator<Não estou completamente certo de por que os outros operadores são necessários. Meu melhor palpite é que isso é apenas parte do que significa ter uma ordem total definida em C ++ entre dois tipos, possivelmente diferentes.