Pregunta

¿Hay problemas de comprensión / mantenibilidad que resultan de código como

inVar1 == 0 ? NULL : v.push_back(inVar1);
inVar2 == 0 ? NULL : v.push_back(inVar2);

y así sucesivamente.

La idea posiblemente confuso está utilizando el operador ternario para el flujo de programa en lugar de asignación de variable, que es la explicación usual.

No he visto estándares en el trabajo que se ocupan de este uso, así que mientras yo estoy cómodo haciendo esto me gustaría saber si hay una buena razón para no hacerlo.

codificación
¿Fue útil?

Solución

Creo que es confuso y mucho más difícil de leer que simplemente escribiendo;

if (inVar != 0)
  v.push_back(inVar);

tuviera que escanear su ejemplo varias veces para averiguar lo que el resultado sería con certeza. Incluso preferiría una sola línea si () {} comunicado que su ejemplo - y no me gusta de una sola línea de las sentencias if)

Otros consejos

El operador ternario está destinado a devolver un valor.

OMI, no debe mutar estado, y el valor de retorno debe ser utilizado.

En el otro caso, utilice las instrucciones if. Si los estados están destinados para ejecutar bloques de código.

El ternario es una buena cosa, y generalmente promover su uso.

Lo que está haciendo aquí, sin embargo empaña su credibilidad. Es más corto, sí, pero es innecesariamente complicado.

Creo que esto debe ser evitado. Se puede usar un 1 línea si la declaración en su lugar.

if(inVar1 != 0) v.push_back(inVar1);

Los compiladores estos días harán un caso tan rápido como un operador ternario.

meta debe ser lo fácil que es para otro desarrollador de software para leer.

Yo voto por

if ( inVar != 0 )
{
   v.push_back( inVar );
}

¿Por qué los soportes ... porque un día es posible que desee poner algo más ahí y los soportes son pre-hechas para usted. La mayoría de los editores de estos días se los metan en cualquier caso.

La utilización del operador ternario que no gana nada y le duele la legibilidad códigos.

Dado que el operador ternario devuelve un valor que no está utilizando el código es impar. El uso de un if es mucho más clara en un caso como el suyo.

Como litb mencionado en los comentarios, este no es válido ++ C. GCC, por ejemplo, emitirá un error en este código:

error: `(&v)->std::vector<_Tp, _Alloc>::push_back [with _Tp = int, _Alloc =
std::allocator<int>](((const int&)((const int*)(&inVar1))))' has type `void' 
and is not a throw-expression

Sin embargo, esto se puede evitar mediante fundición:

inVar1 == 0 ? (void)0 : v.push_back(inVar1);
inVar2 == 0 ? (void)0 : v.push_back(inVar2);

Pero a qué costo? Y con qué propósito?

No es que utiliza el operador ternario aquí es más concisa de una sentencia if en esta situación:

inVar1 == 0 ? NULL : v.push_back(inVar1);
if(inVar1 != 0) v.push_back(inVar1);

Mientras que, en la práctica, estoy de acuerdo con los sentimientos de los que desalientan este tipo de escritura (cuando se lee, que tiene que hacer un trabajo extra para escanear la expresión de sus efectos secundarios), me gustaría ofrecer

!inVar1 ?: v.push_back(inVar1);
!inVar2 ?: v.push_back(inVar2);

... si vas a oscuras, es decir. GCC permite x ?: y en lugar de x ? x : y. : -)

Yo uso operador ternario cuando tengo que llamar a alguna función con argumentos condicionales -. En este caso, es mejor que if

Comparación:

printf("%s while executing SQL: %s",
        is_sql_err() ? "Error" : "Warning", sql_msg());

con

if (is_sql_err())
    printf("Error while executing SQL: %s", sql_msg());
else
    printf("Warning while executing SQL: %s", sql_msg());

Me parece que el primero es más atractiva. Y cumple SECO, a diferencia de este último - que no es necesario escribir dos casi idénticos líneas.

Creo que sería mejor servido en hacer un adecuado si la estructura. aunque yo prefiero tener siempre los apoyos con mis si las estructuras, en caso tengo que añadir líneas después de la ejecución condicional.

if (inVar != 0) {
    v.push_back(inVar);
}

Creo que a veces la ternaria son un mal necesario en las listas inicializador para los constructores. Yo las utilizo sobre todo para los constructores en el que necesito para asignar memoria y establecer algún puntero al punto en el que antes de que el cuerpo del constructor.

Un ejemplo, supongamos que tiene una clase de almacenamiento entero que quería tener tener un vector como una entrada, pero la representación interna es una matriz:

class foo
{
public:
    foo(std::vector<int> input);
private:
    int* array;
    unsigned int size;
};

foo:foo(std::vector<int> input):size(input.size()), array( (input.size()==0)?
        NULL : new int[input.size])
{
    //code to copy elements and do other start up goes here
}

Esta es la forma en que uso el operador ternario. Creo que no es tan confuso como algunas personas pero sí creo que hay que limitar la cantidad que lo utilizan.

La mayoría de los torturados ternarios (¿cómo es eso de la aliteración?) Lo que veo son simplemente intentos de poner lógica que pertenece realmente en una sentencia if en un lugar donde una sentencia if no pertenece o no puede ir.

Por ejemplo:

if (inVar1 != 0)
  v.push_back(inVar1);
if (inVar2 != 0)
  v.push_back(inVar2);

Producción asumiendo que v.push_back es nula, pero lo que si se trata de devolver un valor que hay que conseguir pasar a otra función? En ese caso, tendría que ser algo como esto:

SomeType st;
if (inVar1 != 0)
  st = v.push_back(inVar1);
else if (inVar2 != 0)
  st = v.push_back(inVar2);
SomeFunc(st);

Pero eso es más de digerir para una pieza de código simple. Mi solución:. Definir otra función

SomeType GetST(V v, int inVar1, int inVar2){
    if (inVar1 != 0)
      return v.push_back(inVar1);
    if (inVar2 != 0)
      return v.push_back(inVar2);        
}

//elsewhere
SomeFunc(GetST(V v, inVar1, inVar2));

En cualquier caso, la cuestión es la siguiente: si tiene algo de lógica que es demasiado torturado por un ternaria sino que estorbar encima de su código si se trata de poner en una sentencia if, lo puso en otro lugar

!
inVar1 != 0 || v.push_back(inVar1);
inVar2 != 0 || v.push_back(inVar2);

patrón común que se encuentra en lenguajes como Perl.

Si tiene varias llamadas a métodos en uno o ambos de los argumentos tenary entonces su mal. Todas las líneas de código, independientemente de lo que la declaración debe ser corto y simple, idealmente no agravan.

Una adecuada si la declaración es más legible, como otros han mencionado. Además, cuando se está pasando a través de su código con un depurador, usted no será capaz de ver fácilmente qué sucursal de una si se toma cuando todo está en una línea o usted está utilizando una expresión ternaria:

if (cond) doIt();

cond ? noop() : doIt();

Mientras que la siguiente es mucho más agradable al paso a través (si tiene las llaves o no):

if (cond) {
    doIt();
}

Como se ha mencionado, no es más corto o más claro que una línea de 1 if. Sin embargo, es también ya no - y no es realmente tan difícil de asimilar. Si conoce el operador ternario, que es bastante obvio lo que está pasando.

Después de todo, yo no creo que nadie tendría problemas si se estuviese asignado a una variable (incluso si fue mutando estado también):

var2 = inVar1 == 0 ? NULL : v.push_back(inVar1);

El hecho de que el operador ternario siempre devuelve un valor - OMI - es irrelevante. Ciertamente hay ningún requisito de que utiliza todos los valores de retorno ... después de todo, una misión devuelve un valor.

Una vez dicho esto, me gustaría reemplazarlo con una sentencia if si me encontré con una rama NULL.

y , si se sustituye una línea de 3 if:

if (inVar == 0) {
   v.doThingOne(1);
} else {
   v.doThingTwo(2);
}

por:

invar1 == 0 ? v.doThingOne(1) : v.doThingTwo(2);

podría dejarlo ... dependiendo de mi estado de ánimo. ;)

scroll top