返回专用模板类的协变类型
Posted
技术标签:
【中文标题】返回专用模板类的协变类型【英文标题】:Return covariant type of specialized template class 【发布时间】:2018-04-01 17:07:32 【问题描述】:我有以下类层次结构:
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。我的 Matrix 基类具有 crtp 样式派生类 MatrixND,并且有一个 N=2 的 MatrixND 特化。
每个类都应该有一个虚函数 getNeighbors 来返回一个 MatrixND 指针。
一切正常,除了 MatrixND 类抱怨 MatrixND 是无效的协变返回类型:
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 继承自 MatrixBase!
我的第二个问题:这是不好的设计,因为我总是会返回原始指针?我读了很多表达式 return new obj..,但也认为这显然是糟糕的设计。是否有其他可能实现相同的目标?
编辑:所以,过了一段时间,我意识到原来的计划行不通,我通过模板类找到了一个更简单的解决方案,我想在其中使用那些类。
无论如何,问题是,为什么专门的 MatrixND 类不能是通用 MatrixND 类中的协变返回类型。我没有找到任何说它是不允许的。
【问题讨论】:
错字?Vector
中的返回类型是MatrixND<2,T>*
?并且MatrixND<2,T>
中有一个N
,应该是2
。
是的,N 是个错误。是的,计划是返回一个指向二维矩阵的指针。
那么你应该在Vector
之前声明MatrixND
。
你说得对,我把它放在最后,但这对我的代码没有任何影响。我转发声明所有类以排除此类错误。
一般的MatrixND<N, T>
应该返回MatrixND<N, T> *
,而不是MatrixND<2, T> *
。
【参考方案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>
在N
!= 2 时不会从MatrixBase<N,T,MatrixND<N,T>>
继承。
要么删除MatrixBase<N,T,MatrixND<N,T>>
中的函数重定义,要么将其返回类型更改为GridMetric<T>
,这将起作用(因为MatrixND<2,T>
继承自GridMetric<T>
)。
【讨论】:
非常感谢!这完全有道理并且有效。无论出于何种原因,我认为我需要通过层次结构传递函数,如果我不这样做,函数就会再次变为纯虚拟,因此类抽象。我仍然需要研究,对于我的目的来说,更好的解决方案是什么,但这已经非常有帮助了:)以上是关于返回专用模板类的协变类型的主要内容,如果未能解决你的问题,请参考以下文章