c++

¿Por qué no podemos hacer una comparación de tres vías en C++?



(6)

Esta pregunta ya tiene una respuesta aquí:

Para resumirlo rápidamente, ¿por qué no es 2 < x < 9 igual a 2 < x && x < 9 ?

Este es el código de prueba que he escrito:

#include <iostream> int main() { int nums[] = { 5 , 1, 10}; // We are gonna check if the number is in the range 2 - 9 for (auto e : nums) { if (2 < e < 9) std::cout << "2 < " << e << " < 9" << std::endl; if(2 < e && e < 9) std::cout << "2 < " << e << " and " << e << " < 9" << std::endl; } std::cin.get(); }

Aquí está la salida que estoy recibiendo:

2 < 5 < 9 2 < 5 and 5 < 9 2 < 1 < 9 2 < 10 < 9

Parece que solo 2 < e && e < 9 funcionan correctamente.


C ++ no lo hizo porque eso habría roto la compatibilidad hacia atrás con C. Por lo tanto, tendrías que buscar otra respuesta hace una década.

No sé si Brian Kernighan o Dennis Ritchie alguna vez consideraron hacerlo de la otra manera, o discutieron su razonamiento. No conozco a nadie que solicite esa característica específica. Sus operadores relacionales siguen las mismas reglas que otros lenguajes de la familia Algol.

Un problema hubiera sido que hace que la gramática sea ambigua: 0 < x < 1 ahora tiene un significado muy diferente que (0 < x) < 1 o 0 < (x < 1) . También está el problema de cómo analizar a < b >= c o a < b == c . Recuerde, no hubo ningún tipo booleano en K&R C. Los operadores lógicos devolvieron int , ya que se presumía que el resultado estaba almacenado en un registro de máquina.

Otra posible razón detrás de esto es que K&R C, según sus diseñadores, no es un lenguaje de alto nivel. Sus operaciones básicas generalmente corresponden a las instrucciones de la máquina en las minicomputadoras en las que se desarrolló. Entonces, una comparación era una instrucción de máquina en ese entonces, y una comparación doble no lo era. Habría sido extraño, dadas las otras elecciones que hicieron, introducir ese azúcar sintáctico en particular en el lenguaje solo para hacer que el código C se lea un poco más como un trabajo de matemáticas.


Dentro de si , debe haber condición booleana. En 2 <x <9 , hay dos condiciones. Y dos condiciones no se pueden calcular en C ++ sin operador entre ellas. Por eso no podemos usar 2 <x <9 .


La expresion

2 < x < 9

se agrupa como

(2 < x) < 9

Y como 2 < x es false (0) o true (1), y ambos son menores que 9, siempre es true .

Entonces, a menos que use operadores sobrecargados para un tipo no incorporado x (entonces sería posible una comparación de 3 vías si 2 < x devolviera una instancia de un objeto proxy en el que < está definido), si desea probar Si x está en el intervalo (2, 9), debes escribirlo de la forma que tienes.


Los operadores de comparación en c ++ toman como argumento dos valores. cuando escribe a<b es lo mismo que operator<(a,b) . y el valor de retorno del operador <es bool. cuando llama a una función en c ++, está calculando la expresión de sus argumentos y luego pasándola a esa función, por lo que llamar a<b<c es lo mismo que el operator<(operator<(a,b),c)

Básicamente, la respuesta a tu pregunta es que en c ++ no hay un operador de comparación (menor que, mayor que ...) que toma tres argumentos


Si C ++ eligiera redefinir a < b < c para alinearse mejor con la notación matemática, sería ambiguo con el significado actual. El significado actual es un poco tonto y está comparando bools con números, pero puede haber un código complicado que se basa en este detalle en el uso de producción.

Y como C ++ le permite definir sus propios tipos con operadores, también tendría que exponer el nuevo ternario < a usted, para que pueda hacer uno para su tipo. ¿Cuál abriría nuevas latas de gusanos si solo definiera un binario < pero no ternario < para su tipo? ¿Debería el compilador empezar a gritarle?


Solo porque este lenguaje no tiene esa característica.

Se podría haber hecho para, pero esto contrastaría con C de una manera no compatible.

Podría haberse hecho C, pero los diseñadores simplemente no hicieron eso.

Ya tienes la forma correcta de hacerlo.

Algunos idiomas diferentes (y más nuevos) son compatibles con esto.