자신의 목록을 포함하는 구조를 만드는 방법은 무엇입니까?

StackOverflow https://stackoverflow.com/questions/915445

  •  06-09-2019
  •  | 
  •  

문제

다음과 같은 동일한 구조의 목록을 포함하는 구조를 만들고 싶습니다.

#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
도움이 되었습니까?

해결책

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

이것이 합법적이지 않아야한다는 가능한 이유를 알 수 없습니다.

다른 팁

어떤 컴파일러를 사용하고 있는지 알려주시겠습니까? 당신이하는 일에는 본질적으로 잘못된 것이 없습니다. 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의 버그임을 확인할 수있었습니다.

다른 답변의 주장과는 달리 실제로 ~ 아니다 다음을 포함하여 모든 표준 컨테이너를 인스턴스화하는 것이 합법적입니다. std::list, 불완전한 유형이 있습니다.( 이에 대한 논의는 예를 들어 참조하십시오. 여기서 불완전한 유형을 벡터에 대한 템플릿 매개변수로 어떻게 사용할 수 있습니까?)

이 요구 사항은 C++17에서만 완화됩니다. std::forward_list, std::list 그리고 std::vector.이전 표준의 경우 최신 버전의 VC 및 gcc에서 작동하는 원본 코드는 비표준 확장입니다.이는 관찰에도 적용됩니다. std::vector.

C++17 이전 버전에서는 이식 가능한 std::list 어떤 계급의 T 해당 클래스의 구성원으로서 다음과 같은 해결 방법이 필요합니다. std::list<T*> 또는 완화된 요구 사항을 이미 이식 가능하게 구현한 Boost.container 라이브러리를 사용하세요.

C++17에서도 불완전한 유형으로 클래스 템플릿 자체만 인스턴스화할 수 있습니다.멤버가 인스턴스화될 때 유형은 여전히 ​​완전해야 합니다.

흥미 롭습니다 - 당신은 a를 만들려고합니다 vector 또는 list 불완전한 유형. 표준을 간단히 살펴보면 C ++ 표준 라이브러리에 포함 된 컨테이너 유형에 대해 이것이 허용되지 않아야하는지 여부는 아무것도 찾을 수 없습니다. 판결은 합리적 인 것 같습니다.

허용되지 않는 이유 : 유형의 객체를 선언 할 수는 없습니다 X 정의 내부 X.

예를 들어 다음 코드는 무한대 깊이 데이터 구조를 생성하기 때문에 컴파일에 실패합니다.

struct X {
    X x;
};

허용되는 이유 : 대부분의 컨테이너는 실시되므로 실제 데이터 요소에 대한 수준의 간접 (포인터)가 필요합니다. 포인터를 선언하는 것은 합법적입니다.X 정의 내부 X.

마지막 단락에서 알 수 있듯이이 문제를 해결하는 일반적인 방법은 포인터 또는 참조를 사용하는 것입니다. X. 예를 들어 다음 두 스 니펫은 잘 컴파일합니다.

struct Y {
    Y* y;
};

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

누구든지 (OK, LITB : -P) 표준 컨테이너 유형에 대한 요구 사항이 무엇인지 알고 있습니까?

코드는 GCC 4.4와 완벽하게 잘 컴파일하고 완벽하게 실행됩니다. 버전 7 이전에 MSVC ++는 완전히 표준을 준수하지 않았습니다. 최신 컴파일러 사용을 고려해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top