返回协变类型的专用模板类

时间:2018-04-01 17:07:32

标签: c++ inheritance covariance crtp

我有以下类层次结构:

template<typename T>
class GridMetric{
  virtual GridMetric* getNeighbors(T value) = 0;
};

template<size_t N, typename T, typename Derived>
class MatrixBase : public GridMetric<T>{
  virtual MatrixBase<N,T,Derived>* getNeighbors(T value){return nullptr;}
};

template<size_t N, typename T>
class MatrixND : public MatrixBase<N,T,MatrixND<N,T>>{
  virtual MatrixND<2,T>* getNeighbors(T value){ /* ... */}
};

template<typename T>
class MatrixND<2,T> : public MatrixBase<2,T,MatrixND<2,T>>{
  virtual MatrixND<2,T>* getNeighbors(T value){ /* ... */}
};

template<typename T>
class Vector : public GridMetric<T>{
  virtual MatrixND<2,T>* getNeighbors(T value){ /* ... */}
};

所以我的抽象类GridMetric有两个派生类,Vector和MatrixBase。 My Matrix Base类具有crtp样式派生类MatrixND,并且有一个N = 2的MatrixND专门化。

每个类都应具有虚函数getNeighbors以返回MatrixND&lt; 2,T&gt;指针。

一切正常,但MatrixND类抱怨MatrixND&lt; 2,T&gt;是一个无效的协变返回类型:

error: invalid covariant return type for ‘MatrixND<2ul, T>* MatrixND<N, T>::getNeighbors(T&) [with long unsigned int N = 3ul; T = double]’
  virtual MatrixND<2,T>* getNeighbors(T& in){

我的第一个问题是为什么以及如何处理?由于MatrixND&lt; 2,T&gt;继承自MatrixBase!

我的第二个问题:这是不好的设计,因为我总是会返回原始指针?我读了表达式返回new obj ..很多,而且这显然是糟糕的设计。还有其他可能性来实现同样的目标吗?

编辑:所以,经过一段时间后,我意识到,最初的计划不会成功,我通过模板化课程找到了一个更容易的解决方案,我想在那里使用那些类。

无论如何,问题在于,为什么专门的MatrixND类不能成为一般MatrixND类中的协变返回类型。我没有发现任何说不允许的事情。

1 个答案:

答案 0 :(得分:1)

  • MatrixND<2,T>,基本情况,无需解释。
  • Vector<T>继承自GridMetric<T>,因此任何来自GridMetric<T>(包括此处MatrixND<2,T>)的内容都可以。

但是,一般形式MatrixND<N,T>N!= 2)继承自MatrixBase<N,T,MatrixND<N,T>>,它将虚函数重新定义为:

virtual MatrixBase<N,T,Derived>* getNeighbors(T value){return nullptr;}

强制MatrixND<N,T>的返回类型现在(至少)从MatrixBase<N,T,MatrixND<N,T>>派生。
不是GridMetric<T>(对于Vector<T>)或MatrixBase<2,T,MatrixND<2,T>>(对于专业化MatrixND<2,T>),而是:MatrixBase<N,T,MatrixND<N,T>>,(N! = 2)。

为什么这不是协变返回类型?因为MatrixND<2,T>!= 2时MatrixBase<N,T,MatrixND<N,T>>不会从N继承。

删除MatrixBase<N,T,MatrixND<N,T>>中的功能重新定义或将其返回类型更改为GridMetric<T>,这样就可以了(因为MatrixND<2,T>继承自GridMetric<T>)。