避免c++(部分)模板专门化中的代码重复
Avoiding code repetition in C++ (partial) template specialization
我有一个类Vector,它表示给定模板类的数学向量。我希望能够以两种不同的方式保存矢量:
template <class T>
class Vector
{
private:
T* elements;
};
和
template <class T, unsigned int D>
class Vector
{
private:
T elements[D];
};
在第一个例子中,我在构造函数和析构函数中使用new和delete来分配和释放数组。现在,由于我不想为两个类编写两次所有方法,而且由于我有两个同名但模板参数不同的类,因此它甚至不会以这种方式编译,因此我想将这两个类合并为一个类,如下所示:
template <class T, int D = -1>
class Vector
{
public:
Vector<T, D> add(const Vector<T, D>& add) const;
private:
T elements[D];
};
template <class T>
class Vector<T, -1>
{
public:
Vector<T, D> add(const Vector<T, D>& add) const;
private:
T* elements;
};
所以第二部分只是第一部分的部分模板专门化。如果没有给出维度,应该使用动态分配选项(D的默认参数)。作为一个例子,我添加了一个函数来计算两个向量的和。现在我的问题是,我必须给出两个实现逻辑上只是一个函数。每当我访问元素数组时,它在动态和静态Vector类中的语法完全相同。我能否以某种方式将这两种实现合并为add函数的一个实现(以及所有类似的函数)?如果我不能解决这种方式的问题,你有其他的想法,如何创建矢量类与动态和静态内存分配?
我会选择基于策略的设计,类似于std::vector
处理分配的方式。
你的意思是:
- 定义一个类来存储vector元素,但只提供一个最小的接口。( )
- 定义独立于元素在策略中的存储方式的向量接口。它以独立于该实现的方式访问元素。策略类应该作为模板类型参数(它可以有一个默认值)添加,这样向量类的用户就可以选择使用哪个策略。继承策略类或添加其类型的成员(如果不想在公共接口中公开策略接口,则是私有的)。
示例(这里使用聚合而不是继承):
// The policy default implementation:
template <class T, int D>
class VectorStorage
{
T elements[D];
public:
T& operator[](int x) {
return elements[x];
}
const T& operator[](int x) const {
return elements[x];
}
};
class VectorStorage<T, -1>
{
T* elements; // (for allocation, see below)
public:
T& operator[](int x) {
return elements[x];
}
const T& operator[](int x) const {
return elements[x];
}
};
// The vector implementation, independent of the storage,
// but defaulting to the one above:
template <class T, int D = -1, class Storage = VectorStorage<T,D>>
class Vector
{
Storage storage;
public:
Vector<T, D> add(const Vector<T, D>& add) const {
// Access your elements using "storage[x]"
}
};
注意,需要为策略类提供合适的构造函数(对于动态存储类型,在构造过程中需要大小)。为所有的专门化提供一个唯一的构造函数接口,而不仅仅是为需要它的那个;并在vector的构造函数中适当地调用构造函数:
// within class VectorStorage<T,-1>:
VectorStorage(int size) : elements(new T[size]) {}
~VectorStorage() { delete[] elements; }
// within class VectorStorage<T,D>:
VectorStorage(int /* ignored */) {}
// within class Vector:
Vector(int size) : storage(size) {}
或者,为了支持像Vector<int,5> myVector;
这样的客户端代码(即静态大小版本的默认构造函数),提供一个只允许在静态大小版本中调用的默认构造函数:
Vector() : storage(D) {
static_assert(D != -1, "The default constructor is only allowed for the static-sized version of Vector.");
}
现在用户甚至可以使用Vector
和std::vector
作为存储后端:Vector<int, -1, std::vector<int>>
或Vector<int, 5, std::vector<int>>
。甚至是Vector<int, 5, std::array<int,5>>
我会做如下的事情,即只专门化数据部分:
template <class T, int D = -1>
class VectorData
{
public:
int size() const { return D; }
protected:
T elements[D];
};
template <class T>
class VectorData<T, -1>
{
public:
explicit VectorData(int size) : elements(size) {}
int size() const { return elements.size(); }
protected:
std::vector<T> elements;
};
template <class T, int D = -1>
class Vector : protected VectorData<T, D>
{
public:
using VectorData<T, D>::VectorData;
Vector add(const Vector& add) const
{
Vector res(*this);
for (int i = 0; i != this->size(); ++i) {
res.elements[i] += add.elements[i];
}
return res;
}
};
- C++我的数学有什么问题,为什么我的代码不能正确循环
- 代码在main()中运行,但在函数中出现错误
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 编译包含字符串的代码时遇到问题
- 我在c++代码中生成了一个运行时#3异常
- 如何在linux终端中同时编译和运行c++代码
- 为cl.exe(Visual Studio代码)指定命令行C++版本
- 在Linux for Windows上编译C++代码时出错
- 我的字符计数代码计算错误.为什么
- 孤立代码块在结构中引发异常
- 在编译C++代码(具有dlib和opencv)到WASM时面临问题
- Clang拒绝类模板的嵌套类仅通过专门化定义的代码是正确的吗
- 如果模板的错误代码在If(false)中,我必须专门化模板吗
- 下面的模板专门化代码是非标准的,或者是vs - c++中的错误
- 避免c++(部分)模板专门化中的代码重复
- 在模板专门化中优化循环和避免代码重复
- 避免专门化模板中的代码重复
- 这个模板部分专门化代码有什么问题?
- 即使具有显式实例化,也不会为显式专门化模板生成代码
- 在此代码示例中使用了哪种模板专门化