Pergunta

Existem problemas de entendimento / manutenção que resultam de código como

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

e assim por diante.

A idéia possivelmente confusa é usar o operador ternário para fluxo de programas em vez de atribuição variável, que é a explicação usual.

Não vi padrões de codificação no trabalho que abordam esse uso, então, enquanto me sinto confortável em fazer isso, gostaria de descobrir se há uma boa razão para não fazê -lo.

Foi útil?

Solução

Eu acho que é confuso e muito mais difícil de ler do que simplesmente digitar;

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

Eu tive que digitalizar seu exemplo várias vezes para descobrir qual seria o resultado com qualquer certeza. Eu até preferiria uma instrução de linha única se () {} do que o seu exemplo-e eu odeio instruções de linha única :)

Outras dicas

O operador ternário deve retornar um valor.

IMO, ele não deve mutar o estado e o valor de retorno deve ser usado.

No outro caso, use as instruções if. Se as declarações pretendem executar os blocos de código.

O ternário é uma coisa boa, e geralmente promovo seu uso.

O que você está fazendo aqui, no entanto, mancha sua credibilidade. É mais curto, sim, mas é desnecessariamente complicado.

Eu acho que isso deve ser evitado. Você pode usar uma instrução de 1 linha se em seu lugar.

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

Atualmente, os compiladores serão tão rápidos quanto um operador ternário.

Seu objetivo deve ser o quão fácil é para outro desenvolvedor de software ler.

Eu voto em

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

Por que os colchetes ... porque um dia você pode querer colocar outra coisa lá e os colchetes são antes de você. A maioria dos editores hoje em dia os colocará de qualquer maneira.

Seu uso do operador ternário não lhe ganha nada e você prejudica a legibilidade dos códigos.

Como o operador ternário retorna um valor que você não está usando é um código ímpar. O uso de um if é muito mais claro em um caso como o seu.

Como Litb mencionou nos comentários, este não é válido C ++. O GCC, por exemplo, emitirá um erro neste 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

No entanto, isso pode ser lançado por elenco:

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

Mas a que custo? E com que finalidade?

Não é como usar o operador ternário aqui é mais conciso do que uma declaração IF nessa situação:

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

Enquanto, na prática, concordo com os sentimentos daqueles que desencorajam esse tipo de escrita (ao ler, você precisa fazer um trabalho extra para digitalizar a expressão por seus efeitos colaterais), eu gostaria de oferecer

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

... Se você está indo para obscurecer, é isso. O GCC permite x ?: y no lugar de x ? x : y. :-)

Eu uso operador ternário quando preciso chamar alguma função com argumentos condicionais - neste caso, é melhor então if.

Comparar:

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

com

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

Acho que o primeiro é mais atraente. E está em conformidade com SECO Princípio, diferentemente do último - você não precisa escrever duas linhas quase idênticas.

Eu acho que você seria melhor servido para fazer uma estrutura adequada se. Eu até prefiro sempre ter aparelho com minhas estruturas if, caso eu tenha que adicionar linhas posteriormente à execução condicional.

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

Eu acho que às vezes o ternário é um mal necessário nas listas de inicializador para os construtores. Uso -os principalmente para construtores onde quero alocar memória e definir algum ponteiro para apontá -lo antes do corpo do construtor.

Um exemplo, suponha que você tivesse uma aula de armazenamento inteiro que você queria fazer um vetor como entrada, mas a representação interna é uma 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
}

É assim que eu uso o operador ternário. Eu não acho que seja tão confuso quanto algumas pessoas, mas acho que se deve limitar o quanto elas o usam.

A maioria dos ternários torturados (como é isso para aliteração?) Eu vejo são apenas tentativas de colocar a lógica que realmente pertence a uma declaração IF em um local onde uma declaração IF não pertence ou não pode ir.

Por exemplo:

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

Trabalha assumindo que o V.Push_back é nulo, mas e se estiver retornando um valor que precisar ser passado para outra função? Nesse caso, teria que parecer algo assim:

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

Mas isso é mais para digerir uma peça de código tão simples. Minha solução: defina outra função.

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));

De qualquer forma, o ponto é o seguinte: se você tem alguma lógica que é torturada demais para um ternário, mas irá desordenar seu código se for colocado em uma declaração IF, coloque -a em outro lugar!

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

padrão comum encontrado em idiomas como o Perl.

Se você tiver várias invocações de método em um ou ambos os argumentos tenários, então está errado. Todas as linhas de código, independentemente de qual afirmação deve ser curta e simples, idealmente não composta.

Uma declaração se for mais legível, como outros mencionaram. Além disso, quando você está passando pelo seu código com um depurador, não poderá ver prontamente qual ramo de um se for levado quando tudo estiver em uma linha ou você está usando uma expressão ternária:

if (cond) doIt();

cond ? noop() : doIt();

Considerando que o seguinte é muito melhor para passar (se você tem os aparelhos ou não):

if (cond) {
    doIt();
}

Como mencionado, não é mais curto ou mais claro que uma linha de 1 linha se. No entanto, também não é mais - e não é realmente tão difícil de se divertir. Se você conhece o operador ternário, é bastante óbvio o que está acontecendo.

Afinal, acho que ninguém teria um problema se estivesse sendo atribuído a uma variável (mesmo que estivesse mutação de estado também):

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

O fato de o operador ternário sempre retornar um valor - IMO - é irrelevante. Certamente não há necessidade de usar todos os valores de retorno ... afinal, uma tarefa retorna um valor.

Dito isto, eu o substituiria por uma declaração IF se o encontrasse com um ramo nulo.

Mas, se substituiu uma linha 3 se a instrução:

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

com:

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

EU poderia Deixe isso ... dependendo do meu humor. ;)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top