2013-08-24 38 views
5

關於unique_ptr和不完整類型已經有很多關於SO的問題,但沒有人能給我一個概念來理解爲什麼以下不會工作:C++ 11:unique_ptr抱怨不完整的類型,但不是當我包裝它時

// error: ... std::pair<...>::second has incomplete type 
template<typename K, typename T> struct Impl { 
    typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type; 
    std::unique_ptr<iter_type> ptr; 
    Impl() : ptr(new iter_type()) {} 
}; 

int main() { Impl<int,int>(); return 0; } 

而以下作用:

template<typename K, typename T> struct Impl { 
    struct Wrapper { 
    typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type; 
    iter_type iter; 
    }; 

    std::unique_ptr<Wrapper> ptr; 
    Impl() : ptr(new Wrapper()) {} 
}; 

int main() { Impl<int,int>(); return 0; } 

我沒有看到那裏的技術區別是:如果std::pair<...>::second(即Impl<K,T>)是不完整的,以Impl在第一個例子,它應該是不完整的第二個也是Wrapper。另外,如果將unique_ptr包裝在一個結構中就足夠了,那麼 ,爲什麼第一種情況會有限制?

UPDATE

迪特馬爾·庫爾的回答後,我認爲這個問題可以歸納爲以下:

template<typename K, typename T> struct Impl { 
    typename std::unordered_map<K,Impl<K,T>>::iterator ptr; 
}; 

VS

template<typename K, typename T> struct Impl { 
    struct Wrapper { 
     typename std::unordered_map<K,Impl<K,T>>::iterator iter; 
    }; 
    Wrapper *ptr; 
}; 

回答

3

在第一種情況下的問題不完整的類型與std::unordered_map<K, Impl<K, T>一起使用:要確定iterator是什麼,部分std::unordered_map<K, Impl<K, T> ne在僅僅聲明Impl的時候編輯實例化。 std::unique_ptr<...>與錯誤無關。您可以刪除使用iter_type,因爲typedef需要驗證它是一種類型。

另一方面,在將迭代器類型的使用封裝到Wrapper中時,在構造器實現之前不會使用此嵌套類型。當然,行內定義的函數表現爲如果類只是完全定義,並且它們執行外面的類的定義,即,需要的Wrapper定義當上述代碼等價於

template<typename K, typename T> struct Impl { 
    struct Wrapper { 
    typedef typename std::unordered_map<K,Impl<K,T>>::iterator iter_type; 
    iter_type iter; 
    }; 

    std::unique_ptr<Wrapper> ptr; 
    Impl(); 
}; 
template<typename K, typename T> 
Impl<K, T>::Impl() : ptr(new Impl<K, T>::Wrapper()) {} 

即,並實例化,定義了Impl

+0

你的意思是不同之處在於''Impl'類被認爲**完全實現之前''Wrapper'構造函數沒有被編譯?所以包裝者只是在編輯順序可能完全相同的情況下,將整個構建過程人爲地分爲兩步: –

+0

@JoSo:類模板的成員在使用時被實例化。 'Wrapper'是一個類模板的成員,它只用於構造函數的定義。 'typedef'實際上不是一個成員,並且定義類模板'Impl'它是一種實例化的類。所以,是的,使它成爲一個兩階段的過程,避免了類型的問題,但尚未被定義。 –

+0

不應該有辦法告訴編譯器「是的,這種類型真的存在!」?我的意思是,我也可以說'struct NewType; NewType * ptr;'在課堂內部沒有定義NewType並且它可以工作!這只是規範/實施方面的弱點,還是背後有更深層次的原因? –

相關問題