それ自体のリストを含む構造体を作成するにはどうすればよいですか?
質問
次のような同じ構造のリストを含む構造を作成したいと考えています。
#include <list>
struct Url
{
CString strUrl;
std::list<Url> children;
};
int main()
{
Url u1, u2;
u1.children.push_back(u2);
}
このコードはコンパイルされていません。でも交換すると std::list
と std::vector
正常に動作しています。どうすればこれを機能させることができますか std::list
?
出力ウィンドウに次のエラーが表示されます。
c:\program files\microsoft visual studio\vc98\include\list(29) : error C2079: '_Value' uses undefined struct 'Url'
E:\test\Test.cpp(23) : see reference to class template instantiation 'std::list<struct Url,class std::allocator<struct Url> >' being compiled
c:\program files\microsoft visual studio\vc98\include\functional(185) : error C2079: 'value' uses undefined struct 'Url'
c:\program files\microsoft visual studio\vc98\include\list(285) : see reference to class template instantiation 'std::binder2nd<struct std::not_equal_to<struct Url> >' being compiled
E:\test\Test.cpp(23) : see reference to class template instantiation 'std::list<struct Url,class std::allocator<struct Url> >' being compiled
解決
あなたはVC6のバグのようです何のためworkroundが必要な場合は、動的にリストを作成します:
#include <list>
#include <string> // I don't use MFC
struct Url
{
std::string strUrl;
std::list<Url> * children;
Url() {
children = new std::list <Url>;
}
~Url() {
delete children;
}
};
int main()
{
Url u1, u2;
u1.children->push_back(u2);
}
一部はメンバーと同じタイプのリストが許可されている理由を尋ねた(と私の見解では、彼らがある)しているとき、
Url array[5];
例えばメンバーはならないように。私はどちらか、標準で何かを見つけることはできませんが、sizeof( std:;list <T>)
は、それがリストである事には依存しません。
list <T> {
listEntry <T> * first;
};
、その後に対処するために何未知の大きさがありません。質問者の問題に対処し、次の最小限のコードを考えてみます:
template <typename T> struct A {
};
struct B {
A <B> b;
};
私は、これは法的てはならないことをすべての可能な理由を見ることができません。
他のヒント
あなたが使用しているコンパイラに教えてください。あなたがやっていることと、本質的には何も問題はありません。私はVS2008のSP1上で、次を試してみましたが、それは問題をコンパイルしません。
#include <list>
struct Url
{
std::string name;
std::list<Url> children;
};
int _tmain(int argc, _TCHAR* argv[])
{
Url u1,u2;
u1.children.push_back(u2);
return 0;
}
あなたはおそらくリストを含めることを忘れていましたか?
編集
OPは、Visual Studio 6.0を使用しているとニールはそれがVS6のバグが実際にあることを確認することができました。
他の回答で主張に反して、それは確かにあるのありませんの不完全な型で、std::list
を含む任意の標準コンテナをインスタンス化する法的。 (言語弁護士の議論をタグ付けこのことから、例えば見る方法不完全な型は、ここでベクトルにテンプレートパラメータとして使用することができますか?の)
この要件は、std::forward_list
、std::list
とstd::vector
のためにC ++ 17で緩和します。以前の規格のため、VCとGCCの新しいバージョンで作業元のコードは、非標準の拡張です。また、これはstd::vector
であなたの観測に適用されます。
で事前C ++ 17には、移植性とクラスのメンバーとして、いくつかのクラスstd::list
のT
を持っている、あなたはstd::list<T*>
のような回避策が必要か、すでに移植性リラックスした要件を実装boost.containerライブラリを使用します。
でもC ++ 17で、あなただけの不完全な型とクラステンプレート自体をインスタンス化することができることに注意してください。任意のメンバーがインスタンス化されるときにタイプがまだ完了していなければならない。
興味深いですね -- あなたは vector
または list
不完全なタイプ。この標準をざっと見た限りでは、これが C++ 標準ライブラリに含まれるコンテナ型に対して許可されるべきであるかどうかを示すものは見つかりません。どちらの判決も合理的であるように思われます。
許可されない理由: 型のオブジェクトを宣言することはできません X
の定義の中で X
.
例えば。次のコードは、無限の深さのデータ構造を作成するため、コンパイルに失敗します。
struct X {
X x;
};
それが許可される理由: ほとんどのコンテナーはサイズ変更可能であるため、実際には実際のデータ要素への間接的なレベル (ポインター) が必要です。~へのポインタを宣言することは合法ですX
の定義の中で X
.
最後の段落が示すように、この問題を回避する通常の方法は、ポインターまたは参照を使用することです。 X
. 。例えば。次の 2 つのスニペットは問題なくコンパイルされます。
struct Y {
Y* y;
};
struct Z {
std::list<Z*> zl;
std::vector<Z*> zv;
};
誰か (OK、つまり litb :-P) 標準コンテナ タイプの実際の要件を知っていますか?
のコードは、GCC 4.4で完璧にコンパイル そして、完全に実行されます。バージョン7より前MSVC ++は、完全に標準規格に準拠していませんでした。あなたは、新しいコンパイラを使用して検討すべきである。