Search code examples
c++stlvisual-c++-6

How to create a structure which contains a list of itself?


I want to create a structure which contains a list of same structure like this:

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

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

This code is not compiling. But when I replace std::list with std::vector it is working fine. How can I make this working with std::list?

Output window contains the following error.

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

Solution

  • If you need a workround for what seems to be a VC6 bug, create the list dynamically:

    #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);
    }
    

    Some have asked why lists of the same type as members are allowed (and in my view they are) when

    Url array[5]; 
    

    for example as a member would not be. I can't find anything in the standard either, but sizeof( std:;list <T>) is not dependent on the thing it is a list of. Suppose list was implemented as (some pseudo C++ here):

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

    then there is no unknown size to deal with. Consider the following minimal code that addresses the questioners problem:

    template <typename T> struct A {
    };
    
    struct B {
        A <B> b;
    };
    

    I can't see any possible reason that this should not be legal.