继承与专业化

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.它也不会为执行空基类优化的编译器增加任何空间开销(很常见).