2015-12-22 20 views
35

Po prostu ciekawi mnie, dlaczego ten mały kawałek kodu kompiluje się poprawnie (i bez ostrzeżeń) w Visual Studio. Może wynik jest taki sam z GCC i Clang, ale niestety nie mogę ich teraz przetestować.Kompilacja Visual Studio C++ dziwne zachowanie

struct T { 
    int t; 
    T() : t(0) {} 
}; 

int main() { 
    T(i_do_not_exist); 
    return 0; 
} 
+1

wyjątkowo interesujące! najwięcej błędów kompilatora WTF, jakie kiedykolwiek widziałem! –

+2

również * int (i_do_not_istnieje) * działa poprawnie, ale z nieokreśloną zmienną ostrzeżenie –

+4

Kompiluje również z g ++: http://coliru.stacked-crooked.com/a/d8dd5a50af7c888d – NathanOliver

Odpowiedz

42

T(i_do_not_exist); jest deklaracja obiekt o tym samym znaczeniu, jak T i_do_not_exist;.

N4567 § 6.8 [stmt.ambig] p1

Jest dwuznaczność w gramatyce udziałem ekspresję oświadczenie S i deklarację y: AN wyrażenie-oświadczenie z funkcji stylu jawna konwersja typów (5.2.3), ponieważ jej najbardziej lewe podwyrażenie może być nie do odróżnienia od deklaracji , w której pierwszy deklarator rozpoczyna się od . W tych przypadkach oświadczenie jest deklaracją .

§ 8.3 [dcl.meaning] P6

w zgłoszeniu T D gdzie D ma postać

(D1)

typu zamkniętego declarator-id jest taki sam jak podany deklarator-id w deklaracji

T D1

Nawiasy nie zmieniają typ osadzonego declarator-id, ale mogą zmieniać wiązanie kompleksowe declarators.

+19

Czasem nienawidzę C++ ... jak właśnie teraz. –

+4

to jest głupia decyzja –

+0

Dlatego należy użyć inicjalizacji listy 'T {i_do_not_istnieją}, która powoduje błąd kompilatora. – henje

17

Ponieważ określa zmienną typu T:

http://coliru.stacked-crooked.com/a/d420870b1a6490d7

#include <iostream> 

struct T { 
    int t; 
    T() : t(0) {} 
}; 

int main() { 
    T(i_do_not_exist); 
    i_do_not_exist.t = 120; 
    std::cout << i_do_not_exist.t; 
    return 0; 
} 

Powyższy przykład wygląda głupie, ale składni dopuszczalną powodu.

Lepszym przykładem jest:

int func1(); 
namespace A 
{ 
    void func1(int); 
    struct X { 
     friend int (::func1)(); 
    }; 
} 

Prawdopodobnie inne przykłady można znaleźć.