如何在子类上创建运算符返回子类类型?

时间:2014-05-18 21:48:44

标签: c++ operator-overloading

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

1 个答案:

答案 0 :(得分:1)

使用奇怪的重复模板模式(CRTP)。

基类templatePoint_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中找到selfis_base_of明智,因为它会收到一些拼写错误。