Return 专用模板的协变类型 class
Return covariant type of specialized template class
我有以下 class 层次结构:
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){ /* ... */}
};
所以我的抽象 class GridMetric 有两个派生的 classes,Vector 和 MatrixBase。我的 Matrix Base class 具有派生的 crtp 样式 class MatrixND 并且有一个专门化的 MatrixND 与 N=2.
每个 class 都应有一个虚拟函数 getNeighbors 到 return MatrixND<2,T> 指针。
一切正常,除了 MatrixND class 抱怨 MatrixND<2,T> 是无效协变 return 类型:
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<2,T> 继承自 MatrixBase!
我的第二个问题:是不是设计不好,因为我总是 return 原始指针?我读了表达式 return new obj.. 很多,但也认为这显然是糟糕的设计。是否有其他可能实现同样的目标?
编辑: 所以,过了一段时间,我意识到,原来的计划是行不通的,我通过模板化 [=32] 找到了一个更简单的解决方案=],我想在其中使用那些 classes.
无论如何,问题来了,为什么专用 MatrixND class 不能是通用 MatrixND class 中的协变 return 类型。我没有找到任何说不允许的内容。
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>
的 return 类型现在(至少)派生自 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).
为什么这不是协变 return 类型?因为当 N
!= 2.
时 MatrixND<2,T>
不继承自 MatrixBase<N,T,MatrixND<N,T>>
要么删除 MatrixBase<N,T,MatrixND<N,T>>
中的函数重新定义,要么将其 return 类型更改为 GridMetric<T>
,这将起作用(因为 MatrixND<2,T>
继承自 GridMetric<T>
).
我有以下 class 层次结构:
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){ /* ... */}
};
所以我的抽象 class GridMetric 有两个派生的 classes,Vector 和 MatrixBase。我的 Matrix Base class 具有派生的 crtp 样式 class MatrixND 并且有一个专门化的 MatrixND 与 N=2.
每个 class 都应有一个虚拟函数 getNeighbors 到 return MatrixND<2,T> 指针。
一切正常,除了 MatrixND class 抱怨 MatrixND<2,T> 是无效协变 return 类型:
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<2,T> 继承自 MatrixBase!
我的第二个问题:是不是设计不好,因为我总是 return 原始指针?我读了表达式 return new obj.. 很多,但也认为这显然是糟糕的设计。是否有其他可能实现同样的目标?
编辑: 所以,过了一段时间,我意识到,原来的计划是行不通的,我通过模板化 [=32] 找到了一个更简单的解决方案=],我想在其中使用那些 classes.
无论如何,问题来了,为什么专用 MatrixND class 不能是通用 MatrixND class 中的协变 return 类型。我没有找到任何说不允许的内容。
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>
的 return 类型现在(至少)派生自 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).
为什么这不是协变 return 类型?因为当 N
!= 2.
MatrixND<2,T>
不继承自 MatrixBase<N,T,MatrixND<N,T>>
要么删除 MatrixBase<N,T,MatrixND<N,T>>
中的函数重新定义,要么将其 return 类型更改为 GridMetric<T>
,这将起作用(因为 MatrixND<2,T>
继承自 GridMetric<T>
).