专用模板类并添加新接口

Specializing an template class and adding new interfaces

本文关键字:接口 新接口 添加 专用      更新时间:2023-10-16

我有一个通用模板类Vector.预期用途是使用户专用化通用Vector并定义任何自定义操作。例如

using IntVector = Vector<int>;
IntVector operator+ (const IntVector& a, const IntVector& b);

问题是有些操作不能定义为自由函数,例如IntVector& operator+= (const IntVector& b);。要解决此问题,您可以通过继承进行专业化,

class IntVector : public Vector<int> {
public:
IntVector& operator+= (const IntVector& b);
};
IntVector operator+ (const IntVector& a, const IntVector& b);

但是,这存在一个问题,在基模板类上定义的切片运算符返回泛型Vector_view,而不是支持operator+=的专用IntVector_view。您必须使用与基类相同的主体重载 slice 运算符,只是使用不同的返回类型,这很令人讨厌。

这是一个相关的问题,建议创建一个包装器对象,这对于每种具体类型来说都是相当乏味的。有没有简单的方法来创建一个专用化,您可以在其中添加新接口而无需重新定义类型?如果这是唯一的答案,我认为创建泛型基类没有任何意义。

你不需要为+=做任何特别的事情。

如果我误解了这个问题,请纠正我。可以将像operator+=这样的东西定义为自由函数。例如,以下是您如何为std::vector定义它:

#include <vector>
std::vector<int>& operator+=(std::vector<int>& a, std::vector<int> const& b) {
if(b.size() != a.size())
throw std::logic_error("SIN! SIN! SIN!");
auto* b_scan = b.data();
for(int& value : a) {
value += *b_scan++; 
}
return a; 
}

或者,如果要避免污染全局命名空间,可以在与Vector类相同的命名空间中定义它,并且由于依赖于参数的查找,它仍然可以正常工作。

其他运营商呢,比如operator[]

不幸的是,像operator[]这样的东西必须是成员函数。我们可以允许用户通过创建一个调用用户提供的函数的通用模板来定义它的行为:

class Vector {
// Stuff
public:
value_t& operator[] (int idx);
const value_t& operator[] (int idx) const;
// Add this
auto operator[](T index) -> decltype(get_index(*this, index)) {
return get_index(*this, index); 
}
};

用户可以通过定义get_index来控制operator[]的行为。例如,我们可以为Vector<int>提供get_index的定义,如下所示:

Vector_view<int> get_index(Vector<int>& v, std::pair<int, int> p) {
return {v.begin() + p.first, v.begin() + p.second}; 
}

这个定义可以在Vector的定义之后,它不必被向前声明,并且由于operator[]是一个模板,编译器仍然会找到它。您可以在此处查看一个工作示例。