2013-10-11 2 views
7

C++의 템플릿으로 작업하고 있습니다. MSVC 컴파일러로 컴파일 할 때와 Mingw gcc 컴파일러를 사용할 때 템플릿과 친구 클래스를 사용하는 데 차이가 있습니까? 내 코드가 성공적으로 컴파일되고 MSVC로 컴파일 할 때 원하는 출력을 제공하지만 gcc로 컴파일하면 오류가 발생합니다. MSVC와 위의 코드는 출력을 원하는 주지만와 Mingw의 GCC 컴파일러로 컴파일 할 때 오류를 다음 부여합니다 컴파일 할 때 다음은 내 코드,C++ 템플릿 클래스가 다른 컴파일러에서 다르게 동작합니다.

///////////Record.h///////////////////// 
#include "Base.h" 

class Derived1; 
class Derived2; 
template <class TYPE_LIST> class List; 

class FRecord 
{ 
public: 
    FRecord(); 
    virtual ~FRecord(); 

    friend class Base; 
#if _MSC_VER <= 1200 
    friend class List<Derived1>; 
    friend class List<Derived2>; 
#else 
    template <class TYPE_LIST> friend class List; 
#endif 
}; 

/////////////////////////////////////////////////////////////// 

///////////////////Base.h///////////////////////////////// 

class Base 
{ 
public: 
    Base(const HEADER *hc, const FRecord *fr); 
    virtual ~Base();  
    __inline bool IsNonValid() const; 

protected: 
    quint32 Size; 
}; 

///////////////////////////////////// 
// Data 
///////////////////////////////////// 
template <class TYPE_LIST> 
class Data : public TYPE_LIST 
{ 
public: 
    Data(const HEADER *hc, const FRecord *fr) : TYPE_LIST(hc, fr) 
    { 
     QString val = IsNonValid() ? "Non" : ""; 
     LOG0("Data ("<< val << " Valid)"); 
    } 

    virtual ~Data() 
    { 
     LOG0("Data deleted"); 
    } 
}; // Data 

/////////////////////////////////////////////////////////////////////////////////////// 

Base.h:1154: error: there are no arguments to 'IsNonValid' that depend on a template parameter, so a declaration of 'IsNonValid' must be available 
Base.h:1553: error: 'Size' was not declared in this scope 

은 무엇이 문제에 대한 해결 방안이 될 수있다 ? 미리 감사드립니다.

답변

10

MSVC는 2 단계 이름 조회를 올바르게 구현하지 않습니다. 이 오류를보고 할 때 GCC가 정확합니다.

원인은 템플리트의 매개 변수에 의존하지 않는 (VC의 경우) 템플리트가 정의 될 때 조회되는 것이지 인스턴스화 될 때가 아닙니다.

경우에 컴파일러는 IsNonValid이 기본 클래스에서 올 것이라고 알릴 방법이 없기 때문에 컴파일러는이를 알지 못한다고 합법적으로 불평합니다. 두 가지 해결책이 있습니다 : 그것은 컴파일러 (잠재적으로) 그것을 분명 있도록

  1. IsNonValid에 대한 액세스를 자격은 템플릿 매개 변수에 따라 달라집니다

    QString val = this->IsNonValid() ? "Non" : ""; 
    
    // or 
    
    QString val = TYPE_LIST::IsNonValid() ? "Non" : ""; 
    
  2. 은에 상속 된 이름을 소개 파생 된 클래스 범위 : 이러한

    template <class TYPE_LIST> 
    class Data : public TYPE_LIST 
    { 
    public: 
        using TYPE_LIST::IsNonValid; 
        // the rest as you had it originally 
    

어느 TYPE_LIST의 값이 실제로 알려질 때까지 이름을 종속적으로 만들 것이고, 따라서 검사가 완료 될 때까지 조회를 연기 할 것입니다.

+0

감사합니다. @Angew : 귀하의 솔루션이 내 문제를 해결했습니다. :) ... 이제 어떻게 내 질문의 상태를 SOLVED로 변경할 수 있습니까? – user2765235

+0

@ user2765235 문제가 해결되었다고 생각하는 답변을 수락하십시오. 대답 옆에있는 녹색 체크 표시를 클릭하면됩니다. 자세한 내용은 [help] (http://stackoverflow.com/help/accepted-answer)를 참조하십시오. – Angew

7

gcc가 정확합니다. 인스턴스화 시간까지 조회를 지연하려면 this->을 추가해야합니다. 제대로 두 단계 이름 조회를 구현하지 않는

this->IsNonValid();

MSVC는 부적합가 인스턴스화 될 때까지 모든 조회를 지연시키는입니다.

관련 문제