7

我想创建一个包含相同结构列表的结构,如下所示:

#include <list>
struct Url
{
    CString strUrl;
    std::list<Url> children;
};

int main()
{
    Url u1, u2;
    u1.children.push_back(u2);
}

此代码未编译。但是当我std::liststd::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

如果您需要解决似乎是 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>)不依赖于它是一个列表的东西。假设 list 被实现为(这里是一些伪 C++):

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

那么没有未知的大小可以处理。考虑以下解决提问者问题的最小代码:

template <typename T> struct A {
};

struct B {
    A <B> b;
};

我看不出这不合法的任何可能原因。

于 2009-05-27T12:52:44.033 回答
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 中的一个错误

于 2009-05-27T12:32:17.007 回答
2

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

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

在 C++17 之前的版本中,要使某个类中std::list的某个类T成为该类的成员,您确实需要一种解决方法,例如std::list<T*>或使用 boost.container 库,该库已经可移植地实现了放宽的要求。

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

于 2017-08-07T19:22:01.503 回答
0

有趣——您正在尝试创建一个vectorlist不完整的类型。快速浏览一下标准,我找不到任何说明 C++ 标准库中包含的容器类型是否允许这样做的内容。任何一项裁决似乎都是合理的:

为什么可能不允许:您不能XX.

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

struct X {
    X x;
};

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

正如最后一段所暗示的,解决这个问题的常用方法是使用指向X. 例如,以下两个片段编译得很好:

struct Y {
    Y* y;
};

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

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

于 2009-05-27T12:53:34.297 回答
0

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

于 2009-05-27T13:06:51.057 回答