我正在将一段代码从一个几何库转换为另一个几何库。在我目前的代码中,我有很多专门的Point类,而且我只有一个模板化的类。新模板化的加法运算符,定义为;
template<typename To>
Point<T, N> operator+(const Point<To,N>& p) const;
T
是包含的类型,而N
是该点的维度。
为了提供旧的用法界面,我不得不继承Point类。主要是通过别名某些成员,并添加一些功能;
// Old library, could be indexed by var.x, ...
// New library, can only be indexed via. var[i]
int& x = data[0];
int& y = data[1];
int& z = data[2];
// Old library, supplied this function, new one didn't.
void subclass_function();
这就像一个魅力,这个替代品在整个计划的大多数呼叫站点都有它的作用。也就是说,除非进行算术运算,然后是兼容性类提供的函数,否则说:
IntPoint3 index;
// The scalar multiplication results in the Point<int, 3>.
(index * 2).subclass_function();
错误:Point<int, 3>
没有定义subclass_function()
。
建议的解决方案是什么? - (即让运算符返回子类类型)
注1:我宁愿编辑Point类,也不要在每个专用子类中包装算术运算符的所有重载。
注2:专门的子类不添加状态。
答案 0 :(得分:1)
使用奇怪的重复模板模式(CRTP)。
基类template
类Point_impl
将其派生类型作为参数。
它从运算符返回派生类型。
template<class T, unsigned N, class D>
struct Point_impl {
D* self() { return static_cast<D*>(this); }
D const* self() const { return static_cast<D const*>(this); }
template<typename U, typename D2>
D operator+(Point_impl<U,N,D2> const& o) const {
auto retval = *self();
retval += o;
return retval;
}
};
然后你的派生:
struct Bob:Point_impl<int,3,Bob>{
//...
};
等
我在static_assert
中找到self
并is_base_of
明智,因为它会收到一些拼写错误。