2013-03-09 2 views
1

, 나는상속 및 CRTP

template <class A> 
class CRTP 
{ 
    template <int (A::*Member)()> 
    int func(void * obj) 
    { 
     int result 
     // Do something with Member, like 
     // result = (reinterpret_cast<A*>(obj)->*Member)(); 
     return result; 
    } 
}; 

template <void (A::*Member)()> 같은 클래스를 가지고 요구 사항입니다, 그것은 인수로 전달 될 수 없습니다.

그리고 나는 또한 수업 자료를

class Base : public CRTP<Base> 
{ 
    int aMemberOfBase() {...} 
}; 

그리고이 그 나는

같은 것을 할 것입니다, 나는 또한 파생의 일부 구성원에 CRTP

class Derived : public CRTP<Derived>, public Base 
{ 
    int aMemberOfDerived() {...} 
}; 

을 상속 할 도출

func<&Derived::aMemberOfDerived>(this); 
func<&Base::aMemberOfBase>(this); 

그럴 수 있습니까?

(음, VC는 첫 번째 라인을 컴파일 ++와 두 번째에 대해 읽을 수 없다 ...하지만 파생 보이는 이상한

template <int (Base::*Member)()> int func(void * obj); 
template <int (Derived::*Member)()> int func(void * obj); 

, 나는 그것을 인정 구성원이 있어야합니다. 그러나 코드 조각 다음

template <void (Base::*Member)()> int func() {return 0;} 
template <void (Derived::*Member)()> int func() {return 1;} 

컴파일 및 템플릿의 서명이 동일하지 않습니다와 동일 할 수 없기 때문에, func<&Base::someMember>() != func<&Derived::someMember>()을 반환합니다.)

내가 인정해야 나는 표준이 말하는 것을 잘받지 못한다. 하지만 허용하려는 상속 패턴이 있습니까? 그리고 그렇다면 왜 라인 중 하나가 컴파일되지 않습니까? 또한

, 내가

class Derived : public CRTP<Derived>, public Base 

class Derived : public Base, public CRTP<Derived> 

대신

를 선언하면 어디 선가 뭔가 문제가 있다는 것을 의미한다 (모든 func<...>(...)에) 시간 오류를 컴파일 얻을. 한편

, 나는

template <class A, int (A::*Member)()> int func(void * obj) 

가 CRTP의 필요성을 제거하는 것이라고 알고 있지만, 그것은 func<Derived, &Derived::aMember>()를 작성하는 고통 스럽다이다. 해결 방법이 있습니까 을 허용 할 수 있습니까?

template <class Class, void (Class::*Member)()> class A 
{ 
    void func(void * obj) {...(reinterpret_cast<Class*>(obj)->*Member)();...} 
}; 
template <typename Signature> class B; 

template <typename Class, typename Member> 
class B<&Class::Member> : public class A<Class, &Class::Member> {}; 

+0

관련없는 기사를 읽은 후 Don Clugston은 "가장 빠른 대리인"에서 동일한 문제를 겪었습니다. 그래서 나는 CRTP를 놓고 논쟁을 반복하기로 결정했다. 어쨌든 당신의 도움에 감사드립니다. – Fred

답변

1

기본 멤버 템플릿의 이름을 정규화하여 명확하게 할 수 있습니다. 다음은 작동해야합니다 :

액세스 제어 세부 사항에서 수렁에 빠지지 않도록 모든 것을 공개했습니다.

+0

예. 그러나 나는 자신을 반복하고 싶지 않다. 내 질문은 "이 반복을 피할 수 있습니까? 그렇다면 어떻게? 그렇지 않다면, 왜?" – Fred

+0

그런데 파생 된 클래스에서'Base :: fun <...> (...)'의 사용을 비활성화하기 위해 public/private 상속 ('class Base : private CRTP ')을 사용하려고 했으므로 couln 어떤 종류의 모호함도 없지만'클래스 파생 : public Base, private CRTP '이 작동하지 않습니다. – Fred

+1

@Fred : 액세스 확인은 * before * 과부하 해결 후에 수행됩니다. –