2014-07-24 119 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应该可能是一个单独的问题。 –