2014-07-24 160 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* 
} 

而另一個例子:

​​

如何解決這個任何想法? 謝謝!

+0

嘗試'虛擬空虛foo()= 0' – Ylisar

+0

@Ylisar對不起,這是一個錯誤的例子部分。當然,如果它不是虛擬的,我會有其他問題。 – kotakotakota

回答

6

B<C>B<A>是不同的類型,所以你的第一種情況將永遠不會工作。

你想要做的就是專門爲所有類T的模板,其中std::is_base_of<A, T>::valuetrue。對於這一點,使用一個默認模板參數與偏特:

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; } 
}; 

當A爲T的基極,所述bool參數是true因此使用局部特殊化。否則,使用基本模板。

注意is_base_of返回true即使AT不可訪問的基礎,所以您可能還需要增加一個is_convertible<T*, A*>檢查。

Demo

+0

非常好,非常感謝你! :) – kotakotakota

+0

也許這會更好地分裂成一個不同的問題,但讓我們說,也有一個專業化的std :: vector 。但我也想要一個專門化,當U是A的子類...我試着通過添加另一個參數,默認情況下是bool = false,然後再次有一個bool = std :: is_base_of ::值,但我無法讓它工作......我在這裏有一個[示例](http://coliru.stacked-crooked.com/a/e68f8ba1c81a022e)。有任何想法嗎?另外,我可以在哪裏閱讀關於您使用的部分專業化的類型?我找不到任何東西......謝謝! – kotakotakota

+0

@kotakotakota應該可能是一個單獨的問題。 –