如何创建一个包含自身列表的结构?

时间:2009-05-27 12:27:06

标签: c++ stl vc6

我想创建一个包含相同结构列表的结构:

#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

5 个答案:

答案 0 :(得分:6)

如果你需要一个似乎是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;
};

我看不出任何可能的原因,这不应该是合法的。

答案 1 :(得分: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正在使用Visual Studio 6.0,Neil能够确认它确实是VS6中的错误

答案 2 :(得分:1)

与其他答案中的声明相反,使用不完整类型实例化任何标准容器(包括std::list)确实合法。 (有关此问题的讨论,请参阅例如How can an incomplete type be used as a template parameter to vector here?

此要求仅在std::forward_liststd::liststd::vector的C ++ 17中放宽。对于任何早期标准,使用较新版本的VC和gcc的原始代码是非标准扩展。这也适用于std::vector的观察结果。

在C ++之前的版本17中,为了将某个类std::list作为所述类的成员进行移植,您需要一个像T这样的解决方法或使用提升.container库,已经可以轻松实现宽松的要求。

请注意,即使在C ++ 17中,您也只能使用不完整的类型来实例化类模板。当实例化任何成员时,该类型仍必须完整。

答案 3 :(得分:0)

有趣 - 您正在尝试创建不完整类型的vectorlist。从快速查看标准,我找不到任何说明是否允许C ++标准库中包含的容器类型。裁决似乎是合理的:

为什么不允许这样做:您无法在X的定义中声明X类型的对象。

E.g。以下代码无法编译,因为它会创建一个无限深的数据结构:

struct X {
    X x;
};

为什么允许这样做:大多数容器都可以调整大小,实际上需要一定程度的间接(指针)指向实际的数据元素。在X的定义中声明指向X的指针是合法的。

正如最后一段所暗示的,解决此问题的常用方法是使用指针或对X的引用。例如。以下两个片段编译得很好:

struct Y {
    Y* y;
};

struct Z {
    std::list<Z*> zl;
    std::vector<Z*> zv;
};

有没有人(好吧,我的意思是litb :-P)知道标准容器类型的实际要求是什么?

答案 4 :(得分:0)

该代码与GCC 4.4完美匹配 并且完美地执行。版本7之前的MSVC ++并不完全符合标准。您应该考虑使用更新的编译器。