2017-01-28 8 views
39

次のコードはなぜ地球上で動作しますか?同じクラスのメンバーベクトルを宣言するにはどうすればよいですか?

struct A { 
    std::vector<A> subAs; 
}; 

Aは不完全な型です、そうですか?もしA *のベクトルがあれば、私は理解するでしょう。しかし、ここで私はそれがどのように動作するのか分からない。これは再帰的な定義のようです。

+8

まあ、最低レベルで、これは「再帰的な定義」であるか否か'std :: vector'クラス自体に' A'型のサブオブジェクトが含まれているかどうかによって決まります。 'std :: vector'の典型的な実装では、' A'型の直接的なサブオブジェクトはありません。 'std :: vector'の典型的な実装では、制御されたシーケンスへのポインタを単に含んでいます。これにより、データの再帰が不要になり、不完全な型を引数として使用することが可能になります。ここでの唯一の質問は、言語仕様がそれを許すかどうかです。 – AnT

+0

に関連する[不完全な型をベクターパラメータとしてテンプレートパラメータとして使用するにはどうすればよいですか?](http://stackoverflow.com/q/31345193/1708801) –

答えて

31

paperinto C++17が採用されており、不完全なタイプを特定のSTLコンテナで使用することができます。それ以前は、未定義の動作でした。紙から引用する:イサクア会議の議論に基づいて

、我々はアプローチを進める コンセンサス*を達成 - 「不完全 タイプのコンテナ」が、std::vectorstd::listに範囲を限定し、第1ステップとして std::forward_listを使用します。

標準(強調鉱山)の変化と同様に:vectorをインスタンス化するとき

不完全型Tアロケータ満たすアロケータ-完全-要件場合に使用することができる (17.6.3.5.1)。 Tは、結果として得られる ベクターの特定のメンバーが参照される前に完了しなければならない。

std::vector<T, Allocator>をインスタンス化する際にあなたの場所にデフォルトstd::allocator<T>を残すのであれば、そこにあなたはそれを持って、それは常に紙によると、不完全型Tで動作します。それ以外の場合は、アロケータに不完全タイプTでインスタンス化されているかどうかによって異なります。


Aは右、不完全タイプは?もしA *のベクトルがあれば、私は理解するでしょう。しかし、ここで私はそれがどのように動作するのか分からない。これは再帰的な定義のようです。

再帰はありません。非常に簡略化した形で、それに似て:

技術
class A{ 
    A* subAs; 
}; 

、離れsizecapacityおよびおそらくallocatorstd::vectorからのみ、そのアロケータを介して管理Aの動的配列へのポインタを保持する必要があります。 (そして、ポインタのサイズはコンパイル時に知られている。)

ので、実装は次のようになります。

namespace std{ 

    template<typename T, typename Allocator = std::allocator<T>> 
    class vector{ 

     .... 

     std::size_t m_capacity; 
     std::size_t m_size; 
     Allocator m_allocator; 
     T* m_data; 
    }; 

} 
+5

私はhttp://stackoverflow.com/questions/6517231/ are-c-recursive-types-definitions-possible-in-can-i-put-a-vectortは更新する必要があります:) – kennytm

関連する問題