2010-06-19 32 views
8

最近我遇到了很多typedef和不完整類型的問題,當我更改某些容器時,我的代碼中的分配器。typedef和不完整的類型

我有什麼以前

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

雖然不是完全不知道上面的紋路是否合法,但是這個工作對我每天的實現。當我以爲我可以std::tr1::array做的工作,改變了上面兩行

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

這裏的一切休息,因爲編譯器試圖實例arrayfoo是不完整的類型失敗。我所需要的只是對foo的引用,對陣列的「其他部分」沒有多大興趣。當我創建這樣一個數組時,foo一定會完全可用。

當typedef std::allocator<foo>::pointer foo_ptr被替換爲typedef stack_alloc<foo,10>::pointer foo_ptr時,問題也是如此。其中stack_alloc實現像

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; 
}; 

。假定,value_typepointerreferenceiterator等不依賴於T的完整性,以及明知類不能被實例化不完全型,這種類型定義如何能以通用的方式獨立於特定的容器或分配器?

注:

  • 只是爲了保持完整性,在「真實」的代碼,我用vector小的本地存儲器而不是std::array取代它,但問題依舊不變。
  • stack_alloc代碼遠未完成,只顯示問題的一部分。
  • 我知道數組,sizeof等需要可用的完整類型。但我不創建all_foos類型的對象與不完整foo
  • 我的斷言是指針,引用等不應該依賴於類型的完整性。否則構建像struct foo{ foo_ptr p;};不能被定義。雖然foo_ref可能不是foo&以外的任何東西,但foo_ptr即可。令人驚訝的是GCC實現沒有tr1::array的嵌套指針類型。
  • 大部分人都知道不能做什麼,並且很想知道在這種情況下可以做些什麼。所以期待一個好的設計作爲解決方案。

回答

7

類型必須完整才能在標準容器中使用,或者行爲未定義(第17.4.3.6節)。所以唯一的標準解決方案是在定義該類之前不要製作該typedef

我不明白中間容器是什麼:

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

在任何情況下,你就得有第一定義完整的類型,真的。爲了獲得在類別中定義的typedef,該類別必須被實例化,這意味着必須能夠根據需要使用T

例如,stack_alloc必須有T是一個完整的類型(sizeof(T)工作),否則該類不能被實例化。如果該類不能實例化,則不能從中獲得typedef。 Ergo,你會從來沒有得到typedef出來的,如果T是不完整的。

+0

容器是foo將被存儲的地方。 struct foo; typedef std :: vector > all_foos; typedef all_foos :: pointer foo_ptr;結構欄{foo_ptr p;}; struct foo {std :: vector bars; }; all_foos the_instance;它有道理嗎?如果我定義了struct bar {foo * p; };它可能無法正常工作,因爲alloc可能具有與foo * .typedef foo&foo_ref不同的指針;沒關係,因爲沒有其他方式的參考可以定義。 – abir 2010-06-19 09:43:54

+0

@abir:我無法真正想到指針類型會改變的例子。無論如何,如果你真的想要得到那些typedef,你只需要包含'foo'的完整定義。別無退路。 – GManNickG 2010-06-19 18:04:15

2

Compiller不知道不完整類型的大小,因此它不能實例化它,也沒有爲它分配一些內存。有一個指向對象的指針(如typedef std::tr1::array<foo*, 5> all_foos;)而不是對象本身的實例解決了這個問題。