2013-02-27 1 views
1

XCode 4.5.2에서 아래 정의 된 클래스 Proxy은 컴파일되지 않습니다. 필요한 경우 특정 컴파일러에 대한 자세한 내용을 제공 할 수 있지만 XCode 구성에서 아무 것도 변경하지 않았으므로 기본값이어야합니다. VStudio Express에서 컴파일됩니다. 내가 Proxy를 참조하고있어 완전히 정의되기 전에 -템플릿 클래스의 내부 클래스는 XCode 4.5.2에서 컴파일되지 않습니다.

내가 무슨 일이 일어나고 있는지 이해

No type named 'iterator' in 'std::__1::list<ASW::Cache<std::__1::basic_string<char>>::Proxy, std::__1::allocator<ASW::Cache<std::__1::basic_string<char>>::Proxy>>' 

(캐시에 템플릿 매개 변수가 std::basic_string<char>입니다) :

#include <list> 
#include <boost/thread/tss.hpp> 

template <typename T> 
class Cache 
{ 
public: 
    class Proxy : public T 
    { 
     friend class Cache; 

    private: 
     std::list<Proxy> & m_refList; 
     typename std::list<Proxy>::iterator m_clsPosition; 

     Proxy(std::list<Proxy> & refList) : m_refList(refList) {} 
    }; 

private: 
    std::list<Proxy> m_clsList; 
    typename std::list<Proxy>::iterator m_clsCurrent; 

    static void Release(Proxy * ptrProxy) 
    { 
     ptrProxy->m_refList.splice(ptrProxy->m_refList.m_clsCurrent, 
            ptrProxy->m_refList, 
            ptrProxy->m_clsPosition); 
     if (ptrProxy->m_refList.m_clsCurrent == ptrProxy->m_refList.end()) 
      --(ptrProxy->m_refList.m_clsCurrent); 
    } 

public: 
    Cache() {m_clsCurrent = m_clsList.end();} 
    ~Cache() 
    { 
     if (m_clsList.size() && m_clsCurrent != m_clsList.begin()) 
     { 
      // ERROR - Cache not empty 
     } 
    } 

    typedef boost::shared_ptr<Proxy> Ptr; 

    static Ptr Get() 
    { 
     static boost::thread_specific_ptr<Cache> clsCache; 
     if (clsCache.get() == NULL) 
      clsCache.reset(new Cache()); 

     Proxy * ptrProxy; 
     if (clsCache->m_clsCurrent == clsCache->m_clsList.end()) 
     { 
      clsCache->m_clsList.push_front(Proxy(clsCache->m_clsList)); 
      ptrProxy = &(clsCache->m_clsList.front()); 
      ptrProxy->m_clsPosition = clsCache->m_clsList.begin(); 
     } 
     else 
     { 
      ptrProxy = &(*(clsCache->m_clsCurrent)); 
      ptrProxy->m_clsPosition = clsCache->m_clsCurrent++; 
     } 
     return Ptr(ptrProxy, Release); 
    } 
}; 

컴파일 에러는 라인 typename std::list<Proxy>::iterator m_clsPosition에 . 그렇다면 iterator은 컴파일 할 때 Proxy의 정의가 필요한 이유는 무엇입니까?

데이터 구조의 이유는 1) 오브젝트를 삭제하는 대신 오브젝트를 재사용하고 2) 캐시 된 오브젝트의 반복자를 목록의 해당 위치로 유지함으로써 교정을 촉진하는 것입니다. 누구든지 이러한 문제를 해결하는 방법에 대한 더 좋은 아이디어가 있다면 (이 오류를 해결할 수는 없다), 나는 그것을 듣고 싶어 할 것이다.

+1

기타 의견에서 알 수 있듯이 표준의 제한 때문입니다. 나는 간단히'boost :: container :: list'를 살펴 봤는데, 그것은 불완전한 타입을 포함하도록 설계되었으므로 실행 가능할 것이다. 나는 또한'boost :: ptr_list'를 보았지만, 런타임은리스트에서 노드를 움직이기위한 O (1)가 아니다. 나는 내 자신을 굴리는 것을 끝내 었는데, 나는 이처럼 일반적인 일을하기를 싫어한다. 내가 테스트 한 후에 코드를 게시 할 것이다. – jorgander

답변

2

std::list이 불완전한 유형 (Proxy은 정의 내에 아직 정의되지 않음)으로 인스턴스화 중이므로 코드에 정의되지 않은 동작이 있습니다. [res.on.functions]/2 : 구체적으로는 그 성분에 허용되지 않는 한, 주형 구성 요소를 인스턴스화 할 때 불완전 형 템플릿 인자로 사용되는 경우

는 ... ... 효과가 정의되지 않는다. listworks with incomplete types의 구현을 사용

시도 같은 boost::container::list.

+0

나는 이것이 이런 것이 아닌가 걱정되었다. 나는'std :: list '하지만'std :: list :: iterator'를 인스턴스화하지는 않는다. 컴파일러가'std :: list '을'std :: list :: iterator'를 컴파일하기 위해 컴파일 할 수 있어야하는 이유는 무엇입니까? 그렇다면 왜 표준에서 그런 것이 필요합니까? 부스트 라이브러리 사용에 신경 쓸 필요는 없지만, 가장 단순하고 가장 일반적인 클래스를 선호합니다. – jorgander

+0

@jorgander :'std :: list :: iterator'를 사용하면'std :: list '의 인스턴스화를 의미합니다 (그렇지 않으면'iterator' typedef는 어디에 정의됩니까?). 내가 아는 한,이 정의되지 않은 행동을하는 표준에 대한 정당한 이유는 없습니다 (위원회 측의 시간 부족 및/또는 관련 제안의 부족). – Mankarse

+0

표준위원회에 이유가 있다고 확신하지만 내부 클래스 인스턴스화가 외부 클래스 인스턴스화를 필요로하는 방법을 알지 못합니다. 컴파일러는 템플릿 매개 변수가 전달되기 전에 (예 : 소스 코드에서 처음 구문 분석 될 때) 템플릿의 구조를 인식하고 필요한 것을 컴파일/인스턴스화 만 할 수 있습니다. 일반적으로 MS는 표준을 우회하는 것은 잘못이지만, 나는 그들이 이것에 대해 올바르게 결정했다고 생각합니다. 어쨌든, 그대로입니다. 제 혐의를 확인해 주셔서 감사합니다. – jorgander

관련 문제