¿Por qué se introdujo std :: rangos :: less?
En cppreference onstd::ranges::less , en notas podemos ver que:
A diferencia
std::less
,std::ranges::less
requiere que todos los seis operadores de comparación<
,<=
,>
,>=
,==
y!=
para ser válido (a través de latotally_ordered_with
restricción).
¿Pero por qué? ¿Por qué usaríamos en std::ranges::less{}
lugar de std::less{}
? ¿Cuál es la situación práctica en la que queremos hacerlo less{}
solo si hay otros operadores de comparación definidos, no solo <
uno?
Respuestas
¿Cuál es la situación práctica en la que queremos menos {} solo si hay otros operadores de comparación definidos, no solo el <uno?
No todo lo relacionado con la biblioteca Ranges se basa puramente en lo "práctico". Gran parte de esto se trata de hacer que el lenguaje y la biblioteca tengan sentido lógico.
Los conceptos como característica del lenguaje brindan a la biblioteca estándar la oportunidad de definir combinaciones significativas de características de objetos. Decir que un tipo tiene un operator<
es útil desde la perspectiva puramente práctica de decirle qué operaciones están disponibles para él. Pero realmente no dice nada significativo sobre el tipo.
Si un tipo está totalmente ordenado, entonces lógicamente significa que puede usar cualquiera de los operadores de comparación para comparar dos objetos de ese tipo. Bajo la idea de un orden total, a < b
y b > a
son enunciados equivalentes. Por lo tanto, tiene sentido que si el código está restringido a tipos que proporcionan un orden total, ese código debería poder usar cualquiera de las declaraciones.
ranges::less::operator()
no utiliza ningún otro operador que no sea <
. Pero esta función se limita a los tipos que modelan el totally_ordered
concepto. Existe esta restricción porque eso es lo que ranges::less
es para : comparando tipos que son totalmente ordenado. Podría tener una restricción más estrecha, pero eso estaría descartando cualquier significado proporcionado por el ordenamiento total.
También evita que exponga detalles de implementación arbitrarios a los usuarios. Por ejemplo, digamos que tiene una plantilla que toma algún tipo T
y desea usarla T
en una ranges::less
operación basada en. Si restringe esta plantilla a solo tener un operator<
, entonces ha puesto efectivamente su implementación en la restricción. Ya no tiene la libertad de que la implementación cambie ranges::greater
internamente. Mientras que si hubiera puesto std::totally_ordered
su restricción, dejaría en claro al usuario lo que debe hacer mientras se da la libertad de usar cualquier función que necesite.
Y dado que operator<=>
existe y facilita la implementación de los operadores de pedidos en una función, no hay inconvenientes prácticos . Bueno, excepto por el código que tiene que compilarse tanto en C ++ 17 como en C ++ 20.
Esencialmente, no debería escribir tipos que están "ordenados" simplemente escribiendo operator<
para empezar.
Por lo que puedo decir en base a la propuesta, la idea es simplemente simplificar el diseño de los objetos de función. std::less
es una clase de plantilla que requiere un parámetro de plantilla y representa una comparación homogénea. Este parámetro de plantilla se puede omitir por defecto, lo std::less<void>
que permite comparaciones heterogéneas. El argumento parece ser que el caso homogéneo es innecesario, ya que se maneja bien con el enfoque heterogéneo, por lo que el diseño se puede simplificar considerablemente y no se necesita una plantilla de clase.
En cuanto a por qué operator<
se requieren los otros operadores además , no estoy completamente seguro. Mi mejor suposición es que esto es solo parte de lo que significa tener un orden total definido en C ++ entre dos tipos, posiblemente diferentes.