2014-12-22 13 views
7

compilable przykład:Zewnętrzne szablon na szablonie parametryzowane z rodzaju incompete

main.cpp

#include "test.h" 

int main(int argc, char* argv[]) { 
    auto myPtr = std::unique_ptr<MyClass>(getMyPtr()); 
} 

test.h

#ifndef TEST_H 
#define TEST_H 

#include <memory> 

class MyClass; 
extern template class std::unique_ptr<MyClass>; 
MyClass* getMyPtr(); 

#endif 

test.cpp

#include "test.h" 

class MyClass {}; 
template class std::unique_ptr<MyClass>; 
MyClass* getMyPtr() { return new MyClass; } 

g ++ 4.9.2 narzeka

In file included from c:/devel/mingw32/i686-w64-mingw32/include/c++/memory:81:0, 
       from main.cpp:4: 
c:/devel/mingw32/i686-w64-mingw32/include/c++/bits/unique_ptr.h: In instantiation of 'void std::default_delete<_Tp>::operator()(_Tp*) const [with _Tp = MyClass]': 
c:/devel/mingw32/i686-w64-mingw32/include/c++/bits/unique_ptr.h:236:16: required from 'std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp = MyClass; _Dp = std::default_delete<MyClass>]' 
main.cpp:64:53: required from here 
c:/devel/mingw32/i686-w64-mingw32/include/c++/bits/unique_ptr.h:74:22: error: invalid application of 'sizeof' to incomplete type 'MyClass' 
    static_assert(sizeof(_Tp)>0, 
        ^

chociaż MojaKlasa powinny być widoczne w momencie konkretyzacji szablonu. Czemu?

Edytuj: poprawiono literówkę w przykładzie.

+0

'extern klasy szablon std :: unique_ptr ;' jest to linia mising symbol? 'szablon szablonu extern std :: unique_ptr my_symbol;' Również drugi z 'test.cpp':' szablon klasa std :: unique_ptr my_symbol; ' –

+3

@ πάνταῥεῖ: właściwie to wcale nie brakuje symbolu! Ta deklaracja mówi kompilatorowi, że inna jednostka tłumaczeniowa zapewni instancję odpowiedniego szablonu klasy! –

+0

@ DietmarKühl Ah, THX dla wyjaśnienia. Nie znałem jeszcze tej składni. Codziennie uczę się czegoś nowego :-D. –

Odpowiedz

6

Skutki deklaracji instancji, czyli gwarancja, że ​​szablon nie jest tworzony w sposób dorozumiany, nie stosuje się do inline funkcji zgodnie z 14.7.2 [temp.explicit] pkt 10:

wyjątkiem dla funkcji śródliniowych, deklaracji z typami wywnioskowanymi z ich wartości inicjalizującej lub zwrotnej (7.1.6.4), zmiennych stałych typów literowych, zmiennych typów referencyjnych i specjalizacji szablonów klas, jawne deklaracje wystąpienia mają efekt tłumienia niejawnego tworzenia instancji do których się odnoszą. [Uwaga: intencją jest, aby wbudowana funkcja, która jest przedmiotem jawnej deklaracji inicjacji, będzie nadal domyślnie tworzona, gdy zostanie użyty odr (3.2), aby można było rozważyć ciało do wstawiania, ale że nie jest to kopia spoza linii funkcji wbudowanej zostanie wygenerowany w jednostce tłumaczeniowej. -Naga końcowa]

Standardowa biblioteka wyraźnie deklaruje dowolną z jej funkcji jako inline. Oznacza to, że użycie deklaracji inicjacji nie ma wpływu na wymaganie dotyczące typów definiowanych za pomocą standardowej klasy szablonów biblioteki (o ile nie określono inaczej, oczywiście). gcc definiuje destruktor dla std::unique_ptr<...> w definicji tego szablonu klasy, czyniąc go niejawnie wbudowanym. Oto przykład źródło wykazując problem: w zależności od tego, czy DECL_ONY definiuje to kompilator lub nie:

template <typename T> 
struct foo 
{ 
    ~foo() 
#ifdef DECL_ONLY 
     ; 
#else 
    { static_assert(sizeof(T), "defined!"); } 
#endif 
}; 

#ifdef DECL_ONLY 
template <typename T> 
foo<T>::~foo() { static_assert(sizeof(T), "defined!"); } 
#endif 

class MyClass; 
extern template struct foo<MyClass>; 

int main(int , char* []) { 
    foo<MyClass> f; 
} 
+2

Próbowałem extern szablon również default_delete, dostałem tę samą wiadomość. – Smiles

+1

@Cynic: wystarczy. Problem w rzeczy samej jest czymś różnym: funkcje "inline" są wyłączone z veing ​​z instancji zewnętrznej i funkcje są zdefiniowane [niejawnie] 'inline'. –

+0

Po prostu założyłem, że w tym przypadku generowana jest nieaktualna wersja funkcji, podobnie jak w wirtualnych wirtualnych.Teraz widzę, że nie było żadnego powodu, aby zakładać, że (z powodu jawnego tworzenia instancji w innej jednostce kompilacji). – Smiles

Powiązane problemy