No exemplo de Stroustrup, o que o cólon significa em "retorno 1: 2"?

163

Eu não entendo um uso particular de dois pontos.

Encontrei no livro A linguagem de programação C ++ de Bjarne Stroustrup, 4ª edição, seção 11.4.4 "Chamada e retorno", página 297:

void g(double y)
{
  [&]{ f(y); }                                               // return type is void
  auto z1 = [=](int x){ return x+y; }                        // return type is double
  auto z2 = [=,y]{ if (y) return 1; else return 2; }         // error: body too complicated
                                                             // for return type deduction
  auto z3 =[y]() { return 1 : 2; }                           // return type is int
  auto z4 = [=,y]()−>int { if (y) return 1; else return 2; } // OK: explicit return type
}

Os dois pontos confusos aparecem na linha 7, na declaração return 1 : 2. Não tenho a menor idéia do que poderia ser. Não é um rótulo ou operador ternário.

Parece um operador ternário condicional sem o primeiro membro (e sem o ?), mas nesse caso eu não entendo como ele poderia funcionar sem uma condição.

Piockñec
fonte
6
É um erro de compilação no meu final (gcc e clang). Além disso, todas essas linhas precisam de ponto e vírgula, mas ainda assim um erro.
Cruz Jean
216
Nota do moderador: pense com muito cuidado antes de votar para encerrar isso como uma pergunta de "erro de digitação". Sim, o problema é um erro de digitação, mas não é um erro de digitação que o solicitante fez. Pelo contrário, é encontrado em um livro publicado. Isso significa que essa pergunta e suas respostas podem ser úteis para outras pessoas no futuro, o que é um forte contra-indicador para fechá-la como erro de digitação. (ATUALIZAÇÃO: Este tópico está sendo discutido no Meta ; sinta-se à vontade para pesar lá.)
Cody Gray
3
Talvez a melhor resposta seja: tente compilar o código; se não compilar, é uma boa indicação de que é um erro de digitação.
jrw32982 suporta Monica
Eu posso pensar em vários exemplos que não conseguem compilar (ou até causar um erro interno do compilador) em um compilador, mas são aceitos sem problemas em outro
J. Antonio Perez
1
@ John Eu apenas tentei algumas expressões de dobra com o MSVC e elas não foram compiladas. Tão claramente que todo o capítulo que acabei de ler deve ser um erro de digitação? ;) Os compiladores C ++ falham ao compilar o código C ++ válido o tempo todo, pois a linguagem é absurdamente complicada.
Voo

Respostas:

205

É um erro de digitação no livro. Veja Errata para as 2ª e 3ª impressões da linguagem de programação C ++ . O exemplo deve ser como abaixo:

auto z3 =[y]() { return (y) ? 1 : 2; }
SM
fonte
11
Por que (y)e não apenas y?
Little Helper
7
@LittleHelper Talvez seja uma prática recomendada ou algo assim, eu sempre a vejo assim. Talvez para evitar confusão com comparações mais complicadas ...
RedWolf Programas
28
Pessoalmente, costumo usar (cond) ? a : bpara maior clareza - isso me ajuda a evitar interpretações erradas, por exemplo, a declaração foo = x > y ? a : bcomo foo = x ...ao percorrer o código.
User1686
8
@LittleHelper Não é realmente necessário lá. No entanto, em uma macro de função, é uma prática recomendada colocar parênteses em volta dos argumentos onde eles são usados, porque, caso contrário, a expansão dos argumentos poderá gerar um comportamento inesperado. Considere uma macro semelhante à função para dobrar um valor "foo (x) x * 2" onde você o chama com "foo (2 + 3)". O resultado será 2+ (3 * 2) porque o argumento é expandido como está e as regras de precedência assumem o controle. Se sua macro for "foo (x) (x) * 2", você receberá corretamente (2 + 3) * 2. Pode ser que o Stroustrup tenha o hábito de usar esse estilo em qualquer lugar para garantir a segurança da codificação.
Graham
2
@ Graham Muito improvável. Stroustrup essencialmente não grava macros de função (as funções embutidas em C ++ são melhores). Muito mais provável é que o operador ternário tenha regras de precedência um tanto complicadas, portanto é bom esclarecer habitualmente a precedência com parênteses.
Martin Bonner apoia Monica
19

Parece-me um simples erro de digitação. Provavelmente deve ser:

auto z3 =[y]() { return y ? 1 : 2; }

Observe que, como o lambda não aceita nenhum parâmetro, os parênteses são opcionais. Você pode usar isso em vez disso, se preferir:

auto z3 =[y] { return y ? 1 : 2; }
Jerry Coffin
fonte
11

return 1 : 2; é um erro de sintaxe, não é um código válido.

Uma declaração correta seria mais parecida com isso return (y) ? 1 : 2;.

Remy Lebeau
fonte