2014-07-24 4 views
1

순수 추상 기본 클래스가 있다고 가정 해 보겠습니다. 클래스 템플릿은이 인터페이스를 구현하며 특수화되어 있습니다. 자, 내 문제는이 전문화는 전문 분야의 하위 클래스를 처리 할 수 ​​있어야한다는 것입니다. 그래서 enable_if를 시도했지만 하위 클래스가 추상적으로 끝납니다 ... 어떻게하면이 문제를 해결할 수 있습니까?C++ 추상 기본 클래스가있는 서브 클래스 템플릿 특수화

// This example doesn't work because a subclass of A does not satisfy the 
// specialization for B<T>::foo() 
class A { 
public: 
    virtual void foo() = 0; 
}; 

template <class T> 
class B : public A { 
    ... 
public: 
    ... 
    void foo(); 
    ... 
}; 

void B::foo() { 
    ... 
} 

template <> 
void B<A>::foo() { 
    ... 
} 

class C : A { 
    ... 
public: 
    ... 
    void foo(); 
    ... 
}; 

int main() { 
    B<C> bar; // I was like "this is gonna work!! :) :D" 
    bar.foo(); // But this calls B::foo() instead of B<A>::foo()... :'(*sob* 
} 

그리고 또 다른 예 :이 문제를 해결하는 방법에 대한

// This example doesn't work because B ends up being abstract 
class A { 
public: 
    virtual void foo() = 0; 
}; 

template <class T> 
class B : public A { 
    ... 
public: 
    ... 
    template <class U=T> 
    typename std::enable_if<!std::is_base_of<U, A>::value, void>::type 
    foo() { 
     ... 
    } 

    template <class U=T> 
    typename std::enable_if<std::is_base_of<U, A>::value, void>::type 
    foo() { 
     ... 
    } 
}; 

class C : A { 
    ... 
public: 
    ... 
    void foo(); 
    ... 
}; 

int main() { 
       // I got excited thinking this would work \(^.^)/ 
    B<C> bar; // and then it didn't because B is abstract /(-_-)\ ... 
    bar.foo(); 
} 

어떤 아이디어 예에 의해

? 감사합니다.

+0

보십시오'가상 void foo() = 0' – Ylisar

+0

@Ylisar 죄송합니다, 그것은 예제의 일부에 오타였습니다. 물론 가상이 아니라면 다른 문제가있을 것입니다. – kotakotakota

답변

6

B<C>B<A>은 고유 한 유형이므로 첫 번째 경우는 절대로 작동하지 않습니다.

true 인 모든 클래스 T에 대해 템플릿을 전문적으로 지정하려는 것입니다. 이를 위해, 부분 특수화와 기본 템플릿 매개 변수를 사용 :

A는 T의 기본입니다
template <class T, bool = std::is_base_of<A, T>::value> 
class B : public A { 
public: 
    void foo() override { std::cout << "A is not base of T!" << std::endl; } 
}; 


template <class T> 
class B<T, true> : public A { 
public: 
    void foo() override { std::cout << "A is base of T!" << std::endl; } 
}; 

에서, bool 매개 변수 때문에 부분 특수화를 사용 true입니다. 그렇지 않으면 기본 템플리트가 사용됩니다. AT의 액세스 할 수없는 기본 경우에도 당신은 또한 is_convertible<T*, A*> 검사를 추가 할 수 있도록 is_base_oftrue가 반환

참고.

Demo.

+0

우수, 대단히 감사합니다 !! :) – kotakotakota

+0

아마도이 질문은 다른 질문으로 나눌 수 있지만, std :: vector 에 대한 전문화가 있다고 가정 해 봅시다. 하지만 U가 하위 클래스 인 경우에 대한 전문화도 필요합니다 ... 기본 매개 변수에 bool = false를 추가 한 다음 bool = std :: is_base_of를 :: 값으로 다시 사용하는 다른 매개 변수를 추가하여 시도했습니다. 나는 그것을 작동시킬 수 없었다. 나는 [예제] (http://coliru.stacked-crooked.com/a/e68f8ba1c81a022e)를 여기에 가지고있다. 어떤 아이디어? 또한, 당신이 사용하는 부분 전문화의 유형에 대해서는 어디에서 읽을 수 있습니까? 나는 아무것도 찾을 수 없었다 ... 고마워! – kotakotakota

+0

@kotakotakota 아마도 별개의 질문 일 수 있습니다. –