2012-06-12 14 views
12

Jest to kod:Forward deklaracja klasy stosowanych w funkcji szablonu nie jest kompilowany przez brzękiem ++

class A; 

template <class T> 
void fun() { 
    A a; 
} 

class A { 
public: 
    A() { } 
}; 

int main() { 
    fun<int>(); 
    return 0; 
} 

g ++ 4.5 i 4.7 g ++ kompiluje to bezbłędnie. Ale clang ++ 3.2 (trunk) daje ten błąd:

main.cpp:5:6: error: variable has incomplete type 'A' 
    A a; 
    ^
main.cpp:1:7: note: forward declaration of 'A' 
class A; 
    ^

Który kompilator jest wtedy zgodny ze standardem C++?

+1

Ponieważ próbujesz utworzyć obiekt typu "A", kompilator musi znać jego rozmiar, którego nie może poznać bez obejrzenia pełnej definicji, więc klang będzie tutaj (ale nie mam referencji) . –

+0

Czy jest jakiś przełącznik dostarczony przez clang, aby skompilować taki kod? – Sashank

Odpowiedz

12

Which compiler is right then according to C++ standard?

Obie są poprawne. To źle sformułowany program. Kopalnia nacisk:

N3290 14.6¶9
If a type used in a non-dependent name is incomplete at the point at which a template is defined but is complete at the point at which an instantiation is done, and if the completeness of that type affects whether or not the program is well-formed or affects the semantics of the program, the program is ill-formed; no diagnostic is required.

To dzyń ++ i inne kompilatory zrobić wydać diagnostyczny tutaj jest miły do ​​dodałem cecha, ale diagnoza nie jest obowiązkowe. Ta klauzula "program jest źle sformułowany, nie jest wymagana diagnostyka" daje deweloperowi kompilatorowi swobodę panowania nad wszystkim w takich okolicznościach i nadal jest zgodny.

+0

dlaczego programista nie jest nawet poinformowany przez g ++, że coś jest nie tak? powinno być tak, aby oba kompilatory były poprawne, ale jedna wykonuje swoją pracę, a druga robi coś zupełnie innego? – scdmb

+1

Celem jest umożliwienie leniwego przetwarzania szablonów. Standard pozwala implementacjom odroczyć szczegółowe analizowanie do momentu, w którym tworzony jest szablon. Klasa "A" jest znana w momencie tworzenia, więc kompiluje.Nadal jest źle sformułowany, ponieważ inny plik może "# dołączyć" do definicji twojego szablonu, zdefiniować zupełnie inną klasę "A" i stworzyć inną "zabawę ()". Nie udało się połączyć, ponieważ narusza regułę jednej definicji (nawet jeśli zakwalifikowałeś "fun" jako 'inline'). –

5

Clang jest poprawny, o ile wiem. W twojej funcji nie znamy rozmiaru A, a od twojego przydziału A, musisz znać jego rozmiar. Moim zdaniem, gcc jest sposobem na wybaczenie tutaj.

+0

clang jest dobry, wykrywając problem, ale brak diagnozy gcc również jest poprawny. Zobacz moją odpowiedź dla szczegółów. –

0

kompilator Comeau nie lubi to albo:

"ComeauTest.c", line 5: error: incomplete type is not allowed 
    A a; 
    ^

Jednak moje próby znalezienia rozdział i wers w standardowej C++ były bezowocne. Wydaje się ukryty pomiędzy liniami i interakcjami "punktu tworzenia", "rozpoznawania nazw". Punkty 14.6/8 i 14.6/9 normy z 2003 r. Wydają się istotne.

+0

Nie mam specyfikacji pod ręką, ale wiem, że została dodana reguła (jako rozdzielczość DR), aby uczynić swój kod "źle sformułowanym, bez diagnostyki" jakiś czas po C++ 98 lub C++ 03. znajduje się w akapicie, który mówi o nieprawidłowych definicjach szablonów. –

1

clang++ stosuje prawidłowe działanie, co zostało opisane w części 4.6/9 standardu (n1905).


Templates 14.6/9 Name resolution

If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; the name is bound to the declaration (or declarations) found at that point and this binding is not affected by declarations that are visible at the point of instantiation.


aby to w prostszy sposób; jeśli nazwa jest nie zależna od parametru-szablonu, powinna znajdować się w zasięgu, w którym znajduje się definicja; Dlatego przed definicją template<typename T> void fun() musisz zdefiniować A.

+2

N1905 jest nieco stary. To od 2005 roku. N3291 był (chyba) ostatecznym projektem. –

Powiązane problemy