7

次のような同じ構造のリストを含む構造を作成したいと思います。

#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
4

5 に答える 5

5

使用しているコンパイラを教えてください。あなたがしていることに本質的に悪いことは何もありません。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はVisualStudio6.0を使用しており、NeilはそれがVS6のバグであることを確認できました。

于 2009-05-27T12:32:17.007 に答える
5

VC6のバグと思われる問題の回避策が必要な場合は、リストを動的に作成します。

#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>)それがリストであるものに依存していません。リストが(ここではいくつかの疑似C ++)として実装されたと仮定します。

list <T> {
   listEntry <T> * first;
};

その場合、処理する未知のサイズはありません。質問者の問題に対処する次の最小限のコードを検討してください。

template <typename T> struct A {
};

struct B {
    A <B> b;
};

これが合法であってはならないという考えられる理由はわかりません。

于 2009-05-27T12:52:44.033 に答える
2

他の回答の主張とは反対に、不完全なタイプを含む標準コンテナをインスタンス化することは実際には合法ではありません。std::list(これに関するの議論については、例えば、ここでベクトル化するためのテンプレートパラメータとして不完全な型をどのように使用できるかを参照してください。 )

std::forward_listこの要件は、std::listおよびのC++17でのみ緩和されstd::vectorます。以前の標準の場合、新しいバージョンのVCおよびgccで機能する元のコードは非標準の拡張機能です。これは、を使用した観測にも当てはまりますstd::vector

C ++ 17より前ではstd::list、あるクラスのをそのクラスTのメンバーとして移植可能に持つにstd::list<T*>は、boost.containerライブラリのような回避策が必要です。これは、緩和された要件をすでに移植可能に実装しています。

C ++ 17でも、不完全な型でのみクラステンプレート自体をインスタンス化できることに注意してください。メンバーがインスタンス化されるときは、タイプはまだ完全である必要があります。

于 2017-08-07T19:22:01.503 に答える
0

コードはGCC4.4で完全にコンパイルされ、完全に実行されます。バージョン7より前のMSVC++は、完全に標準に準拠していませんでした。新しいコンパイラの使用を検討する必要があります。

于 2009-05-27T13:06:51.057 に答える
0

興味深い-あなたは不完全なタイプの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)は、標準のコンテナタイプの実際の要件を知っていますか?

于 2009-05-27T12:53:34.297 に答える