¿En qué se diferencia el operador de comparación de tres vías de la resta?


Hay un nuevo operador de comparación <=> en C++20. Sin embargo, creo que en la mayoría de los casos una simple resta funciona bien:

int my_strcmp(const char *a, const char *b) {
    while (*a == *b && *a != 0 && *b != 0) {
        a++, b++;
    }
    // Version 1
    return *a - *b;
    // Version 2
    return *a <=> *b;
    // Version 3
    return ((*a > *b) - (*a < *b));
}

Tienen el mismo efecto. Realmente no puedo entender la diferencia.

Author: Cris Luengo, 2017-12-31

3 answers

El operador resuelve el problema con el desbordamiento numérico que se obtiene con la resta: si se resta un gran número positivo de un negativo que está cerca de INT_MIN, se obtiene un número que no se puede representar como un int, causando así un comportamiento indefinido.

Aunque la versión 3 está libre de este problema, carece totalmente de legibilidad: tomaría algún tiempo entenderla por alguien que nunca ha visto este truco antes. <=> el operador soluciona el problema de legibilidad, demasiado.

Este es solo un problema abordado por el nuevo operador. La sección 2.2.3 de El documento de Herb SutterConsistent comparison habla sobre el uso de <=> con otros tipos de datos del lenguaje donde la resta puede producir resultados inconsistentes.

 49
Author: dasblinkenlight,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-31 21:54:38

Aquí hay algunos casos para los que la resta no funcionará:

  1. unsigned tipos.
  2. Operandos que causan desbordamiento de enteros.
  3. Tipos definidos por el usuario que no definen operator - (quizás porque no es significativo-uno puede definir un orden sin definir una noción de distancia).

Sospecho que esta lista no es exhaustiva.

Por supuesto, uno puede llegar a soluciones para al menos #1 y #2. Pero la intención de operator <=> es encapsular esa fealdad.

 39
Author: Oliver Charlesworth,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-31 13:51:18

Hay algunas respuestas significativas aquí sobre la diferencia, pero Herb Sutter en su documento dice específicamente:

Es para implementadores de tipo: El código de usuario (incluido el código genérico) fuera de la implementación de un operador casi nunca debe invocar un directamente (como ya se descubrió como una buena práctica en otros idiomas);

Así que incluso si no hubiera diferencia, el punto del operador es diferente: ayudar a los escritores de clases a generar comparación operador.

La diferencia principal entre el operador de resta y el operador de" nave espacial " (según la propuesta de Sutter) es que sobrecargar operator- te da un operador de resta, mientras que sobrecargar operator<=>:

  • le da los 6 operadores de comparación de núcleo (incluso si declara el operador como default: no hay código para escribir!);
  • declara si su clase es comparable, es clasificable, y si la orden es total o parcial (fuerte / débil en la clase de Sutter propuesta);
  • permite comparaciones heterogéneas: puede sobrecargarlo para comparar su clase con cualquier otro tipo.

Otras diferencias están en el valor de retorno: operator<=> devolvería un enum de una clase, la clase especifica si el tipo es clasificable y si el tipo es fuerte o débil. El valor devuelto se convertiría en -1, 0 o 1(aunque Sutter deja espacio para que el tipo devuelto también indique distancia, como lo hace strcmp). En cualquier caso, asumiendo el valor de retorno -1, 0, 1, ¡finalmente obtendremos una verdadera función signum en C++! (signum(x) == x<=>0)

 14
Author: Cris Luengo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-02 17:49:49