2013-07-09 2 views
0

"모델"은 파생 된 모든 모델에 있어야하는 데이터 구조와 메서드를 정의하는 기본 클래스입니다. "필터"는 모델의 데이터 구조와 메소드 (모두 모델 기본 클래스에 정의 된 동일한 인터페이스를 사용)를 사용하는 기본 클래스입니다. 여러 파생 모델 및 여러 파생 필터가 있습니다. 파생 된 각 필터는 파생 된 모델에서 작동 할 수 있어야합니다. 모델은 필터와 독립적입니다. 속도가 중요하기 때문에 CRTP (Curiously Recurring Template Pattern)를 사용하여 정적 다형성을 시도하고 있습니다. 이상적으로, Filter가 사용하는 Model의 메소드는 inlineable이어야합니다. 이 클래스 디자인의 시작 부분은 다음과 같습니다.하나의 CRTP 자식 클래스의 데이터/메서드를 다른 클래스에 액세스

이제 필터를 모델에 액세스 할 수있는 메커니즘이 필요합니다. 이 컴파일하면 바로 볼 다중 상속을 시도해보십시오

template <typename DerivedModel> 
class Filter2A : public Filter<Filter2A>, public DerivedModel { 
}; // Filter2A 

를이 (GCC 4.7.1, 특별한 스위치를 사용하여) 실패 관련 유래 게시물을 읽기를 바탕으로

error: type/value mismatch at argument 1 in template parameter list for ‘template<class DerivedFilter> class Filter’ 
expected a type, got ‘Filter2A’ 

이의 템플릿 템플릿을 사용하자 대신 인수. 또한, 대신 MI, 나는 필터를 위해 새로운 코드의 내부 모델을 놓을 게요 :이 작동

template<typename DerivedModel, template<class> class DerivedFilter> 
class Filter { 
public: 
    DerivedModel myModel; // Filter "has a" Model 
    double b_; 
    Filter(const double b) : b_(b) {} 
    double step() { 
    return static_cast<DerivedFilter*>(this)->step(); // ERROR 
    } // step 
}; // Filter 

template<typename DerivedModel> 
class Filter1 : public Filter< DerivedModel, Filter1 > { // CRTP 
public: 
    Filter1(const double b) : Filter< DerivedModel, Filter1 >(b) {} 
    double step() { return b_; } // "b_ was not declared in this scope" 
}; // Filter1 

- static_cast 라인을 제외 :

In member function ‘double Filter<DerivedModel, DerivedFilter>::step()’: 
error: expected type-specifier before ‘DerivedFilter’ 
expected ‘>’ before ‘DerivedFilter’ 
... 

그래서 템플릿 템플릿 매개 변수 DerivedModel을 Model의 메소드에 액세스하려면 다른 구문이 필요합니까? 이 문제를 해결하는 typedef가 있습니까 (몇 가지 시도했지만 성공하지 못했습니다).

또한 제 2 호를 이해하지 못합니다. 모든 것이 공개 되더라도 필터의 b_는 Filter1에서 더 이상 액세스 할 수 없습니다. (b_를 Filter < DerivedModel, Filter1> :: b_로 대체하여 수정할 수 있습니다.) 이것은 간단한 CRTP 코드 예제에서는 필요하지 않았습니다.

답변

2

첫 번째 시도는 아마 제대로만큼 당신이 클래스 이름을 넣어 같이 작동합니다 :

return static_cast<DerivedFilter<DerivedModel>*>(this)->step(); 
: 올바른 static_cast 구문을 사용하는 경우

class Filter2A : public Filter<Filter2A<DerivedModel> >, public DerivedModel { 

은 또한, 두 번째 시도가 작동합니다

컴파일러가 실제 유형으로 바꿀 수없는 템플릿 이름을 언급하는 것이 아니라 이러한 상황에서 특정 유형의 이름을 지정해야합니다. 특정 형식을 해결하기위한 모든 인수가없는 템플릿 이름 자체는 컴파일러에게 실제 형식 (레이아웃 정보를 계산하고 기호를 찾는 등)을 해결하는 데 필요한 정보를 제공하지 않습니다.

심볼은 b_ 심볼과 관련하여 종속 유형 인 상속 된 유형의 멤버입니다. 즉, 템플릿이 선언되었을 때 컴파일러가 유형을 알지 못합니다. 컴파일러에게이 기호는 종속 기호이며 인스턴스화시 찾아야한다는 힌트를 제공해야합니다. b_ 대신 this->b_을 사용해보세요. 또는 클래스 네임 스페이스 한정자를 사용하십시오. 그런 다음 컴파일러는 심볼을 종속 심볼로 처리하고 템플릿 정의 시간이 아닌 템플릿 인스턴스 생성 시간에이를 해결합니다.

+0

낮은 투표 수에도 불구하고 철저한 해결책을 높이 평가하십시오. 이 기호를 해결하기 위해 편의상 "typedef Filter F;"줄을 추가했습니다. "F :: b_"등을 입력 할 수 있습니다. – burningbright

관련 문제