如何使子类上的操作符返回子类类型?

How can I make operators on subclasses return the subclass type?

本文关键字:子类 返回 类型 操作符 何使      更新时间:2023-10-16

我正在将一段代码从一个几何库转换为另一个几何库。在我当前的代码中,我有很多专门化的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:特化子类不添加状态

使用奇怪的重复模板模式(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>{
  //...
};

等。

我在selfis_base_of中发现static_assert也是明智的,因为它捕获了一些拼写错误。