2008-11-20 10 views
38

Czy można przesłać dalej deklarację kontenera STL w pliku nagłówkowym? Na przykład, weźmy następujący kod:Przekaż dalej deklaruje kontener STL?

#include <vector> 

class Foo 
{ 
private: 
    std::vector<int> container_; 
    ... 
}; 

Chcę być w stanie zrobić coś takiego:

namespace std 
{ 
    template <typename T> class vector; 
} 

class Foo 
{ 
private: 
    std::vector<int> container_; 
    ... 
}; 

można to zrobić?

Odpowiedz

27

Zgłaszanie vector w przestrzeni nazw jest nieokreślone zachowanie niezdefiniowane zachowanie. Twój kod może więc działać, ale może również nie, a kompilator nie ma obowiązku informować cię, gdy próba nie zadziała. To jest hazard i nie wiem, czy warto unikać unikania standardowego nagłówka C++.

Zobacz następujący comp.std.C++ dyskusja moderowana.

forward declaring std::vector. Works, but is it legal and standard compliant?

+1

Podążyłem za twoim linkiem do dyskusji, ale ludzie nie wydają się wyciągać wniosków. Najwyraźniej implementacja STL nie może dodawać żadnych parametrów szablonu do standardowych kontenerów. w związku z tym należy zezwolić na przekazanie deklaracji wzoru. – Haplo

+1

Nieokreślone, @Haplo. Jeśli implementacja *, którą używasz, decyduje o zdefiniowaniu zachowania wykraczającego poza to, co mówi standard, jest to świetne, ale wciąż nieokreślone, więc twój kod nie będzie przenośny. Wniosek (sądząc po niezalecanych wypowiedziach) jest taki, że standard powinien na to pozwolić, ale nie, i że są dwa rozwiązania: Zawiń standardowe typy w deklarowane przez użytkownika elementy konstrukcyjne lub po prostu ugryź bullet i dołącz standardowy nagłówek . Ten drugi jest łatwy do zrobienia. –

+1

"Oświadczenia pozostawione bez zastrzeżeń" w grupie Usenet nie są autorytatywnym źródłem. Ale Jerry Coffin ma rację, gdy cytuje [namespace.std]/1. W praktyce, jeśli twój kompilator zdiagnozuje deklaracje 'namespace std' w nagłówkach niesystemowych lub jeśli twoja standardowa biblioteka nie jest zaimplementowana w C++, to możesz mieć problem, ale te rzeczy nigdy się nie zdarzają – Potatoswatter

16

Nie sądzę, ponieważ kompilator nie może wiedzieć, ile miejsca należy przydzielić dla obiektu container_. W najlepszym razie można zrobić:

std::vector<int> *container_; 

i nowy w konstruktorze, ponieważ kompilator zna rozmiar wskaźnika.

+0

dokładnie to, co chciałem powiedzieć – badbadboy

+0

Dobrze, ale to jest problem ze wszystkimi deklaracjami forward, a nie specyficznymi dla tych w 'namespace std'. Odpowiada więc na pytanie "real_", nie na pytanie OP. : P Po prostu nie możemy przekazać dalej - zadeklarujmy coś, a następnie stwórzmy je według wartości, z oczywistych powodów. –

8

Oprócz tego, co mówili inni (z wyjątkiem Adam Rosenfield), może się okazać, że warto wiedzieć, że istnieje sposób usankcjonowane deklarowanych w czasie iostreams i niektórych pokrewnych szablonów: nagłówek <iosfwd> (patrz http://msdn.microsoft.com/en-us/library/1af12yty%28VS.80%29.aspx). Byłoby użyteczne, gdyby standard miał więcej takich nagłówków.