具有共享功能的类模板特化

Tho*_*mas 15 c++ templates template-specialization

我正在编写一个带有模板矢量类型的简单数学库:

template<typename T, size_t N>
class Vector {
    public:
        Vector<T, N> &operator+=(Vector<T, N> const &other);
        // ... more operators, functions ...
};
Run Code Online (Sandbox Code Playgroud)

现在我想要一些专门用于其中一些功能的附加功能.比方说,我想要的功能x(),并y()Vector<T, 2>访问特定的坐标.我可以为此创建一个部分特化:

template<typename T>
class Vector<T, 3> {
    public:
        Vector<T, 3> &operator+=(Vector<T, 3> const &other);
        // ... and again all the operators and functions ...
        T x() const;
        T y() const;
};
Run Code Online (Sandbox Code Playgroud)

但现在我正在重复通用模板中已存在的所有内容.

我也可以使用继承.将通用模板重命名为VectorBase,我可以这样做:

template<typename T, size_t N>
class Vector : public VectorBase<T, N> {
};

template<typename T>
class Vector<T, 3> : public VectorBase<T, 3> {
    public:
        T x() const;
        T y() const;
};
Run Code Online (Sandbox Code Playgroud)

但是,现在的问题是所有运算符都已定义VectorBase,因此它们返回VectorBase实例.这些不能分配给Vector变量:

Vector<float, 3> v;
Vector<float, 3> w;
w = 5 * v; // error: no conversion from VectorBase<float, 3> to Vector<float, 3>
Run Code Online (Sandbox Code Playgroud)

我可以给出Vector一个隐式转换构造函数来实现这个:

template<typename T, size_t N>
class Vector : public VectorBase<T, N> {
    public:
        Vector(VectorBase<T, N> const &other);
};
Run Code Online (Sandbox Code Playgroud)

不过,现在我从转换VectorVectorBase,然后再返回.尽管类型在内存中是相同的,并且编译器可能会优化所有这些,但它感觉很笨,我真的不喜欢潜在的运行时开销,这本质上是一个编译时问题.

有没有其他方法可以解决这个问题?

Rex*_*xar 9

我认为你可以使用CRTP来解决这个问题.这个习惯用法在boost :: operator中使用.

template<typename ChildT, typename T, int N>
class VectorBase 
{    
public:
    /* use static_cast if necessary as we know that 'ChildT' is a 'VectorBase' */
    friend ChildT operator*(double lhs, ChildT const &rhs) { /* */ }
    friend ChildT operator*(ChildT const &lhs, double rhs) { /* */ }
};

template<typename T, size_t N>
class Vector : public VectorBase<Vector<T,N>, T, N> 
{
};

template<typename T>
class Vector<T, 3> : public VectorBase<Vector<T, 3>, T, 3>
{
public:
    T x() const {}
    T y() const {}
};

void test()
{
    Vector<float, 3> v;
    Vector<float, 3> w;
    w = 5 * v;
    w = v * 5;
    v.x();

    Vector<float, 5> y;
    Vector<float, 5> z;
    y = 5 * z;
    y = z * 5;
    //z.x(); // Error !!
}
Run Code Online (Sandbox Code Playgroud)