2014-10-16 36 views
5

Dlaczego kompilator interpretuje ten wiersz jako definicji funkcji, a nie jako definicji zmiennej:Definicja funkcji lub definicja zmiennej?

Y y(X()); 

w poniższym kodzie:

#include <iostream> 

struct X { 
    X() { std::cout << "X"; } 
}; 

struct Y { 
    Y(const X &x) { std::cout << "Y"; } 
    void f() { std::cout << "f"; } 
}; 

int main() { 
    Y y(X()); 
    y.f(); 
} 

VS2010 daje następujący błąd na linii „YF() ; "

left of '.f' must have class/struct/union 

Która część normy opisuje to zachowanie? Odpowiedź na pytanie nie daje szczegółów o tym: Most vexing parse

+1

To nie jest błąd kompilatora. To najbardziej irytujący problem z analizą, sprytnie ukryty. – Bathsheba

+1

Zagłosowano na ponowne otwarcie w oparciu o edycję - cytat z normy byłby w rzeczywistości użyteczny. 6.8 mówi o disamiguating wypowiedzi wyrażenie kontra deklaracje, ale najbardziej denerwujące przetwarzanie jest w rzeczywistości dwuznaczność między dwie deklaracje. – Angew

Odpowiedz

6

Rozważ to:

float foo(int())

Ten deklaruje funkcję foo (przyjmując funkcję powracającego int) Powracasz float.

teraz czytać

Y y(X()); 

jak y jako funkcji (przyjmując funkcję powracającego X) Powracasz Y

Problem pojawia się z powodu C++ most vexing parse

można rozwiązać:

Y y{ X() }; // requires C++11 

lub

Y y((X())); 
    //^ ^notice parenthesis 

Aktualizacja podstawie EDIT:

cytat ze standardowego:

§ 8.2 rozdzielczości Wieloznaczność [dcl.ambig.res]

1 - Niejednoznaczność wynikająca z podobieństwa między odlewem stylem funkcyjnym a deklaracją wymienioną w punkcie 6.8 może również wystąpić w kontekście deklaracji. W tym kontekście wybór znajduje się między deklaracją funkcji a zbędnym zestawem nawiasów wokół nazwy parametru i deklaracją obiektu z rzutowaniem stylu w stylu jako inicjalizatorem. Podobnie jak w przypadku niejednoznaczności wymienionych w 6.8, celem rezolucji jest rozważenie wszelkich konstrukcji, które mogłyby być deklaracją. [Uwaga: deklarację można wyraźnie ujednoznacznić przez rzutowanie w stylu niefunkcji, przez a = w celu wskazania inicjalizacji lub przez usunięcie nadmiarowych nawiasów wokół nazwy parametru. ]

[Example: 

struct S { 
    S(int); 
}; 

void foo(double a) 
{ 
    S w(int(a)); // function declaration 
    S x(int()); // function declaration 
    S y((int)a); // object declaration 
    S z = int(a); // object declaration 
} 
—end example] 

Podobnie inne przykłady po tym.

+2

'Y y = X();' nie jest równoważne 'Y y {X()};'. Prawidłowym rozwiązaniem w C++ 03 jest 'Yy ((X())); – magras

+0

Jednak w niektórych przypadkach' Yy = X(); 'będzie działać zgodnie z przeznaczeniem i będzie bardziej czytelny. – magras

+0

@PetrPervukhin tak zaktualizowany, dzięki – P0W

4

Most vexing parse problem. Y y(X()) to w rzeczywistości deklaracja funkcji o nazwie y, która zwraca Y i odbiera argument funkcji type, która zwraca X i nie otrzymuje nic.

Został rozwiązany w C++ 11 przy użyciu obiektu {} dla obiektu konstruktu.