CRTP

2016-06-08 2 views
5

를 사용하는 경우 컴파일러는 기본 클래스의 메서드를 참조하지 않는 이유는 다음 코드 조각이 :CRTP

struct Iface 
{ 
    virtual int Read() = 0; 

    int Read(int x) { 
     return Read() + x; 
    } 
}; 

template <typename Impl> 
struct Crtp : public Iface 
{ 
    virtual int Read() { 
     return static_cast<Impl&>(*this).ReadImpl(); 
    } 
    //using Iface::Read; 
}; 

struct IfaceImpl : public Crtp<IfaceImpl> 
{ 
    int ReadImpl() { 
     return 42; 
    } 
}; 

int main() 
{ 
    IfaceImpl impl; 
    impl.Read(24); // compilation error 

    Iface& iface = impl; 
    iface.Read(24); // always compiles successfully 
} 

두 MSVC, GCC와 그 소리가이 코드를 거부, 그들이 찾을 수없는 방법 Read(int x)

단을 using Iface::Read에서 Crtp을 주석 처리하면 코드가 성공적으로 컴파일됩니다. 내가 Iface는에 대한 참조를 수강하면이 Read(int x)

왜 이런 일이 않는 호출 할 수

주?

답변

7

왜 이런 일이 발생합니까?

귀하의 문제는 CRTP와 관련이 없습니다. 이것은 일반적인 상속 시나리오에서 발생할 수있는 이름 숨기기 문제입니다.

impl.Read(24);을 호출하면 IfaceImpl의 클래스 범위에서 구성원 함수 이름 Read을 찾을 수 없습니다. 그런 다음 기본 클래스 Crtp의 범위를 검사하고 이름이 Read 인 것을 확인합니다. 그런 다음 이름 조회가 중지되므로 추가 기본 클래스 Iface에있는 int Read(int x)은 여기에서 더 적합 할지라도 과부하 해결을 고려하지 않습니다.

using Iface::Read;ReadCrtp의 클래스 범위에 도입했습니다. 그런 다음 과부하 해결로 올바르게 찾아서 선택할 수 있습니다.

Iface 참조를 통해 전화를 걸면 이름 조회가 제대로 작동합니다.

impl.Iface::Read(24);으로 명시 적으로 (또는 추한대로) 호출 할 수 있습니다.

Unqualified name lookup 참조 : 그 조회가 정지되고 더 이상의 범위가 조사되어 있지 않은 시간에 어떤 종류의 적어도 하나 명의 선언을 찾을 때까지, 후술하는 바와 같이

는 ... 이름 조회의 범위를 검토한다.