我想创建一个包含相同结构列表的结构:
#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
答案 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
)确实不合法。 (有关此问题的language-lawyer讨论,请参阅例如How can an incomplete type be used as a template parameter to vector here?)
此要求仅在std::forward_list
,std::list
和std::vector
的C ++ 17中放宽。对于任何早期标准,使用较新版本的VC和gcc的原始代码是非标准扩展。这也适用于std::vector
的观察结果。
在C ++之前的版本17中,为了将某个类std::list
作为所述类的成员进行移植,您需要一个像T
这样的解决方法或使用提升.container库,已经可以轻松实现宽松的要求。
请注意,即使在C ++ 17中,您也只能使用不完整的类型来实例化类模板。当实例化任何成员时,该类型仍必须完整。
答案 3 :(得分:0)
有趣 - 您正在尝试创建不完整类型的vector
或list
。从快速查看标准,我找不到任何说明是否允许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 ++并不完全符合标准。您应该考虑使用更新的编译器。