2012-12-18 3 views
2

내 위젯 라이브러리에서 어떤 종류의 호출 체인을 초기화하려면 사용자가 제공 한 VIEW 클래스 (!)를 추가하는 다른 클래스에서 파생 될 수 있습니다 (예 : ) 이 :호출 체인에서 CRTP 사용

#include <iostream> 

template<typename VIEW> 
struct App 
{ 
    VIEW view; 
    void init() {view.initialize(); } 
}; 

template<typename DERIVED> 
struct SpecializedView 
{ 
    void initialize() 
    { 
     std::cout << "SpecializedView" << std::endl; 
     static_cast<DERIVED*>(this)->initialize(); 
    } 
}; 

struct UserView : SpecializedView<UserView> 
{ 
    void initialize() {std::cout << "UserView" << std::endl; } 
}; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    // Cannot be altered to: App<SpecializedView<UserView> > app; 
    App<UserView> app; 
    app.init(); 
    return 0; 
} 

는 (사용자 제공 VIEW 클래스 "SpecializedView"로부터 유도되는 경우) 콜 체인의 일종을 달성하는 것이 가능하다 같은 출력 될 것이다 : 물론

console output: 

SpecializedView 
UserView 

그것 준비가 쉽다. 에서 파생 된 유형의 변수가없는 앱은 제외하지만이 코드는 라이브러리에 숨겨져있어 변경해서는 안됩니다. 즉, 라이브러리 코드는 매개 변수로 사용자 파생 유형 만 가져와야합니다. 당신은 너무 initialize() 방법이 존재하는 경우 클래스와 기본 클래스에 initialize()를 호출하고 정의하는 또 다른 기능을 쓸 수

+2

명백한 공개 초기화 방법은 매우 나쁩니다. – Puppy

+1

@DeadMG : 위의 예제 코드는 최소한으로 제거되었습니다! 내 의도를 설명하는 데 필요한 것보다 더 많은 코드를 추가하고 싶지 않았습니다. – fhw72

답변

1

이 : 물론

template <class T> 
void callInitialize(T* t) { 
    t->initialize(); 
    IF_EXISTS(base_class<T>::bc::initialize) 
     callInitialize<base_class<T>::bc>(t); 
} 

, 호출의 순서가 역전 될 수있다.

IF_EXISTS 구현에 대해서는 Is it possible to write a template to check for a function's existence?을 참조하십시오. 또한 base_class<T>은 표준 구조가 아니며 this answer은 자동으로 수행 할 수 없음을 나타냅니다. 의미는 다음과 같을 것이다 :

template<T> 
struct base_class<T> { 
    typedef void bc; 
}; 

template<> 
struct base_class<UserView> { 
    typedef SpecializedView<UserView> bc; 
}; 

아마도 당신의 프레임 워크는이 작업을 수행하는 반자동 방식을 허용한다.

관련 문제