2010-06-19 13 views
8

Ostatnio mam wiele problemów z typedef i niekompletnym typem, kiedy zmieniłem pewne pojemniki, alokatory w moim kodzie.typedef i niekompletny typ

Co miałem wcześniej

struct foo;//incomplete type. 
typedef std::vector<foo> all_foos; 
typedef all_foos::reference foo_ref; 

Choć nie do końca nie jestem pewien, czy powyższe linie są zgodne z prawem, ale to działało na każdym realizacji użyłem. Kiedy myślałem, że mogę wykonać zadanie z std::tr1::array zmienił powyższe dwie linie z

typedef std::tr1::array<foo,5> all_foos; 
typedef all_foos::reference foo_ref; 

Tutaj przerw wszystko jak kompilator próbuje instancję array a nie jako foo jest niekompletny typ. Jedyne, czego potrzebowałem, to odwołanie do foo i niezbyt zainteresowane "innymi częściami" tablicy. foo na pewno będzie całkowicie dostępny po utworzeniu takiej tablicy.

To samo dotyczy problemu, gdy typedef std::allocator<foo>::pointer foo_ptr został zastąpiony przez typedef stack_alloc<foo,10>::pointer foo_ptr. gdzie realizacja stack_alloc jest jak

template<typename T,unsigned N> 
struct stack_alloc 
{ 
    typedef T* pointer; 
    typedef std::tr1::aligned_storage<sizeof(T)*N, std::tr1::alignment_of<T>::value> buffer; 
}; 

Zakładając, że value_type, pointer, reference, iterator etc nie zależy od kompletności T, i wiedząc, że klasa nie może być wystąpienia bez kompletnego typu, jak takie typedef puszka być generowane w sposób ogólny, niezależnie od konkretnego kontenera lub przydziału?

UWAGA:

  • Tylko dla kompletności, w „prawdziwym” kodu używam małą lokalną pamięć vector zamiast zastępując ją std::array, ale problem pozostaje ten sam. Kod
  • jest kompletny i pokazuje tylko część problemu.
  • Wiem, że tablica, sizeof itp. Wymaga pełnego typu dostępnego. Ale NIE tworzę obiektu typu all_foos z niekompletnym foo.
  • Moje stwierdzenie jest takie, że wskaźnik, odnośnik itp. Nie powinien zależeć od kompletności typu. W przeciwnym razie nie można zdefiniować konstrukcji takiej jak struct foo{ foo_ptr p;};. Chociaż prawdopodobnie foo_ref nie może być niczym innym niż foo&, ale może być foo_ptr. Zaskakująco implementacja GCC nie ma zagnieżdżonego typu wskaźnika dla tr1::array.
  • Wiesz głównie, czego nie można zrobić, i interesuje Cię, co można zrobić w tej sytuacji. Więc oczekuję dobrego projektu jako rozwiązania.

Odpowiedz

7

Typ musi być kompletny do użycia w standardowym pojemniku lub zachowanie jest niezdefiniowane (§17 .4.3.6/2). Tak więc jedynym standardowym rozwiązaniem jest, aby nie tworzyć tego typedef, dopóki klasa nie zostanie zdefiniowana.

Nie rozumiem co pojemnik pośredni jest dla:

struct foo;//incomplete type. 
typedef foo& foo_ref; 

W każdym razie, to po prostu trzeba mieć kompletny typ zdefiniowany pierwszy, naprawdę.Aby uzyskać zdefiniowaną klasę typedef, należy utworzyć instancję klasy , która musi być, co oznacza, że ​​cały obiekt musi być w stanie użyć, zgodnie z potrzebami, T.

Na przykład stack_alloc musi być T musi być kompletny (dla sizeof(T) do pracy), w przeciwnym razie klasa nie może być utworzona. Jeśli nie można utworzyć instancji klasy, nie można uzyskać z niej typedef. Ergo, będziesz nigdy dostać typedef z niego, jeśli T jest niekompletna.

+0

Kontener jest miejscem przechowywania foo. struct foo; typedef std :: vector > all_foos; typedef all_foos :: wskaźnik foo_ptr; struct bar {foo_ptr p;}; struct foo {std :: vector barów; }; all_foos the_instance; czy to ma sens? Jeśli zdefiniuję pasek struktury {foo * p; }; NIE może działać, ponieważ alokacja może mieć inny wskaźnik niż foo * .typedef foo & foo_ref; jest ok, ponieważ nie można zdefiniować innego odniesienia do drogi. – abir

+0

@abir: Nie mogę wymyślić przykładu, w którym zmieni się typ wskaźnika. W każdym razie, jeśli naprawdę chcesz uzyskać te typy, musisz po prostu dołączyć pełną definicję 'foo'. Żaden inny sposób. – GManNickG

2

Kompilator nie zna rozmiaru niekompletnego typu, dlatego nie może go utworzyć w instancji ani przydzielić mu trochę pamięci. Posiadanie wskaźnika do obiektu (np. typedef std::tr1::array<foo*, 5> all_foos;) zamiast wystąpienia samego obiektu rozwiązuje ten problem.

Powiązane problemy