5

SO の 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、2 番目の例でも不完全である必要があります。また、構造体でラップするだけで十分unique_ptrな場合、最初のケースに制限があるのはなぜですか?

更新

ディートマー・キュールの答えの後、問題は次のように縮小できると思います。

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

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

1 に答える 1

3

最初のケースの問題は、不完全な型が で使用されているstd::unordered_map<K, Impl<K, T>ことです: が何であるかを判断するには、が単に宣言されているときにiterator、 の一部をインスタンス化する必要があります。エラーとは関係ありません。型であることを確認する必要があるため、 の使用を削除できます。std::unordered_map<K, Impl<K, T>Implstd::unique_ptr<...>iter_typetypedef

一方、イテレータ型の使用を にラップする場合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()) {}

つまり、 の定義Wrapperが必要で、インスタンス化されたときに、Implが定義されます。

于 2013-08-24T23:18:20.123 に答える