Eu não entendo por que isso compila

80

Certamente estou perdendo alguma coisa, mas não entendo por que isso compila (com g ++ e clang ++):

struct A
{
};
struct B
{
};

int main()
{
  A a(B);
}

Primeiro de tudo, Bé um tipo ... não um valor. Como devo interpretar esse código?

Picaud Vincent
fonte
37
Isso é conhecido como o Analisador mais irritante
alter igel
8
@alterigel É mesmo? Nesse caso, não há ambiguidade. Só pode ser uma declaração de função. Não é o A a(B());que poderia ser uma definição variável ou declaração de função.
Walnut3
8
Você ficaria surpreso ao saber que struct A{}; int main() { A(foo); } compila como está , mesmo fooque não cite nada.
precisa saber é
20
@alterigel - esta não é a análise mais irritante. Veja os exemplos na página que você vinculou. Isto é simplesmente uma declaração de função.
Pete Becker
3
@PeteBecker, talvez seja melhor explicar por que isso não é MVP, em vez de apenas afirmar que não é, o que acredito que a noz já fez acima.
precisa saber é o seguinte

Respostas:

84

É interpretada como a declaração de uma função chamada a, que recebe um argumento do tipo Be retorna A.

Brian
fonte
5
E é por isso que é Most e Vexing. A solução: (não que isso realmente resolve nada, uma vez que expõe a má construção)A a{B};
user4581301
23
@ user4581301 - é não o mais parse irritante. É simplesmente uma declaração de função.
Pete Becker
23
Acontece que é apenas uma análise principalmente irritante ...
MooseBoys 4/19
11
A parte mais estranha sobre ele é que C ++ não permite funções aninhadas, mas não permitem declarações dentro de uma função.
The_Sympathizer
6
Parece uma boa motivação para adicionar suporte a funções aninhadas no C ++; Não só eles ser útil, eles transformar esta verruga estranho em um projeto razoável :)
Jeremy Friesner
15

É simplesmente uma declaração de função que declara aser uma função retornando Ae recebendo um parâmetro do tipo sem nome B.

É válido porque declarações de função, em oposição às definições de função, são permitidas nas definições de função.

machine_1
fonte
13

Esse problema é conhecido como a análise mais irritante . A linha A a(B);pode ser interpretada como a declaração de uma função denominadaa retornando um objeto do tipo Ae assumindo um parâmetro do tipo sem nome B.

Uma maneira de evitar esse problema é usar a inicialização uniforme sintaxe de introduzida no C ++ 11, que consiste em usar chaves em vez de parênteses: A a{B};retorna um erro. A linha agora é interpretada como uma declaração de variável inicializada com B, que é um tipo em vez de um valor.

Aqui estão mais informações:

A análise mais irritante: como localizá-lo e corrigi-lo rapidamente

G. Morin
fonte
12
Eu não acho que isso deva ser chamado de " análise mais irritante ". É apenas uma declaração de função usual, como também existe em C. Não há resolução de ambiguidade necessária porque a linha pode ser apenas uma declaração de função, nada mais. Olhe para o seu link. Os exemplos são todos diferentes disso.
Walnut #
3
Embora isso seja verdade, está relacionado à análise mais irritante. É que isso também incluiu um erro de digitação em que um nome de tipo foi usado sozinho em vez de uma variável ou uma chamada de construtor, como provavelmente era a intenção original.
Miral
11
Sim, "Most Vexing Parse" é uma resposta útil nesse caso, mesmo que o caso real da pergunta seja apenas "Slightly Vexing Parse".
jpa
11
@ wlanut: As estruturas vazias struct A { };não são válidas no padrão C, mesmo que alguns compiladores permitam. Solte o aparelho e não haveria problema lá. Além disso, em C, declarar ou definir struct Anão cria um nome de tipo A(você deve prefixá-lo structou incluir em typedef struct A A;algum lugar antes de Aser usado sem o structprefixo). Também em C, não há análise alternativa para a declaração da função - o uso type name(...);simplesmente nunca pode ser uma definição de variável; é sempre uma declaração de função (ou inválida). O código na pergunta não é válido em C. #
Jonathan Leffler