8 c++ inheritance specialization
考虑以下两种使用场景(正如您所看到的那样,即最终用户只对使用Vector2_t和感兴趣Vector3_t):
[1]继承:
template<typename T, size_t N> struct VectorBase
{
};
template<typename T> struct Vector2 : VectorBase<T, 2>
{
};
template<typename T> struct Vector3 : VectorBase<T, 3>
{
};
typedef Vector2<float> Vector2_t;
typedef Vector3<float> Vector3_t;
Run Code Online (Sandbox Code Playgroud)
[2]专业化:
template<typename T, size_t N> struct Vector
{
};
template<typename T> struct Vector<T, 2>
{
};
template<typename T> struct Vector<T, 3>
{
};
typedef Vector<float, 2> Vector2_t;
typedef Vector<float, 3> Vector3_t;
Run Code Online (Sandbox Code Playgroud)
我无法决定哪个是更好的解决方案.继承的明显优势是派生类中的代码重用; 可能的缺点是性能(更大的尺寸,用户可以通过价值等).专业化似乎避免了这一切,但代价是我不得不多次重复自己.
我错过了哪些其他优点/缺点,并且您认为我应该选择哪条路线?
Joh*_*itb 12
我认为,你最终想要的是拥有用户类型
Vector<T, N>
Run Code Online (Sandbox Code Playgroud)
并且取决于N,用户将获得略微不同的东西.第一个不会实现,但第二个将,代码重复的代价.
你可以做的是颠倒继承:
template<typename T, size_t N> struct VectorBase
{
};
template<typename T> struct VectorBase<T, 2>
{
};
template<typename T> struct VectorBase<T, 3>
{
};
template<typename T, size_t N> struct Vector : VectorBase<T, N>
{
};
Run Code Online (Sandbox Code Playgroud)
并实现少数仅依赖于N在适当的基类中具有某些特定值的函数.您可以在其中添加受保护的析构函数,以防止用户Vector通过指针删除实例VectorBase(通常它们甚至不能命名VectorBase:将这些基础置于某个实现命名空间中,如detail).
另一个想法是将此解决方案与另一个答案中提到的解决方案相结合.私有地继承(而不是如上所述)并将包装函数添加到调用基类实现的派生类中.
另一个想法是只使用一个类然后enable_if(使用boost::enable_if)为特定值启用或禁用它们N,或者使用像这样的int-to-type转换器,它更加简单
struct anyi { };
template<size_t N> struct i2t : anyi { };
template<typename T, size_t N> struct Vector
{
// forward to the "real" function
void some_special_function() { some_special_function(i2t<N>()); }
private:
// case for N == 2
void some_special_function(i2t<2>) {
...
}
// case for N == 3
void some_special_function(i2t<3>) {
...
}
// general case
void some_special_function(anyi) {
...
}
};
Run Code Online (Sandbox Code Playgroud)
这样,它对用户来说是完全透明的Vector.它也不会为执行空基类优化的编译器增加任何空间开销(很常见).