混合部分模板专门化和默认模板参数 [英] Mixing partial template specialization and default template parameters
问题描述
我想创建一个通用的向量类,并为几种情况创建专门化。这样的东西(它不编译,但希望传达我的意图):
模板< int dim,typename T = float>
class Vector
{
public:
typedef Vector< dim,T& VecType;
Vector(){/ ** /}
Vector(const VecType& other){/ ** /)
Vector& operator =(const VecType& other){/ ** /}
VecType运算符+(const VecType& other){/ ** /}
VecType operator- / ** /}
T运算符*(const VecType& other){/ ** /}
private:
std :: array< T,dim>元素;
};
template< int dim,typename T>
class Vector< 2>
{
public:
T x()const {return elements [0]; }
T y()const {return elements [1]; }
};
template< int dim,typename T>
class Vector< 3>
{
public:
T x()const {return elements [0]; }
T y()const {return elements [1]; }
T z()const {return elements [2]; }
};
换句话说,我希望元素的默认类型是 float
,并且我希望有 x()
和 y()
code> dim = 2 case和 x()
, y >
dim = 3
的情况下使用 z()
我对错误消息感到困惑:
vector.h:56:10:error: / p>
vector.h:6:10:error:shadows模板parm'int dim'
$ b b
(与 T
相同)。
我该如何正确? (如果可能)
1。
一个模板,只提供实际上是一个参数的模板参数。由于您已将 dim
固定为2或3,因此无需再次指定。
template< typename T>
class Vector< 2,T>
{
....
2。
专门化一个类真的意味着改变整个声明。因此,通用向量< dim,T>
的成员将不能在专用向量< 2,T>
。你可以将泛型 Vector< dim,T>
变成一个内部基类,并创建一个仅用于特殊化的子类:
template< int dim,typename T>
class VectorImpl;
...
模板< int dim,typename T = float>
class Vector:public VectorImpl< dim,T> {};
template< typename T>
class Vector< 2,T> :public VectorImpl< 2,T>
{
public:
T x()const {...}
};
3。
需要定义 VecType
!在模板中,您可以使用 Vector
。将自动推导出具有正确参数的类。
编译的最终结果:
#include< array>
template< int dim,typename T>
class VectorImpl
{
public:
// typedef Vector< dim,T& VecType;
VectorImpl(){}
VectorImpl(const VectorImpl& other){}
VectorImpl& operator =(const VectorImpl& other){return * this; }
VectorImpl operator +(const VectorImpl& other){return * this; }
VectorImpl operator-(const VectorImpl& other){return * this; }
T operator *(const VectorImpl& other){return 0; }
protected:
std :: array< T,dim>元素;
};
template< int dim,typename T = float>
class Vector:public VectorImpl< dim,T> {};
template< typename T>
class Vector< 2,T> :public VectorImpl< 2,T>
{
public:
T x()const {return this-> elements [0]; }
T y()const {return this-> elements [1]; }
};
template< typename T>
class Vector< 3,T> :public VectorImpl< 2,T>
{
public:
T x()const {return this-> elements [0]; }
T y()const {return this-> elements [1]; }
T z()const {return this-> elements [2]; }
};
int main()
{
Vector< 2> v;
Vector< 3> vv;
v + v;
vv.z();
}
I would like to create a generic vector class and create specializations for a few cases. Something like this (it does not compile, but hopefully communicates my intentions):
template<int dim, typename T = float>
class Vector
{
public:
typedef Vector<dim, T> VecType;
Vector() { /**/ }
Vector(const VecType& other) { /**/ )
Vector& operator=(const VecType& other) { /**/ }
VecType operator+(const VecType& other) { /**/ }
VecType operator-(const VecType& other) { /**/ }
T operator*(const VecType& other) { /**/ }
private:
std::array<T, dim> elements;
};
template<int dim, typename T>
class Vector<2>
{
public:
T x() const { return elements[0]; }
T y() const { return elements[1]; }
};
template<int dim, typename T>
class Vector<3>
{
public:
T x() const { return elements[0]; }
T y() const { return elements[1]; }
T z() const { return elements[2]; }
};
In other words, I want the default type of the elements to be float
and I want to have x()
and y()
accessor methods for the dim = 2
case, and x()
, y()
and z()
for the dim = 3
case. I'm a little confused by the error messages:
vector.h:56:10: error: declaration of ‘int dim’
vector.h:6:10: error: shadows template parm ‘int dim’
(same for T
).
How can I do this correctly? (if it's possible)
1.
When partially specializing a template, only supply the template parameters that are actually a parameter. Since you've already fixed dim
to be 2 or 3, there's no need to specify it again.
template<typename T>
class Vector<2, T>
{
....
2.
Specializing a class really means changing the whole declaration. Therefore, the members s of the generic Vector<dim, T>
will not be available in the specialized Vector<2, T>
. You could make the generic Vector<dim, T>
as into an internal base class, and create a subclass just for specialization:
template<int dim, typename T>
class VectorImpl;
...
template<int dim, typename T = float>
class Vector : public VectorImpl<dim, T> {};
template<typename T>
class Vector<2, T> : public VectorImpl<2, T>
{
public:
T x() const { ... }
};
3.
You don't need to define VecType
! Inside a template, you could just use Vector
. It will automatically be deduced to refer to the class with the right parameters.
The end result that compiles:
#include <array>
template<int dim, typename T>
class VectorImpl
{
public:
//typedef Vector<dim, T> VecType;
VectorImpl() { }
VectorImpl(const VectorImpl& other) { }
VectorImpl& operator=(const VectorImpl& other) { return *this; }
VectorImpl operator+(const VectorImpl& other) { return *this; }
VectorImpl operator-(const VectorImpl& other) { return *this; }
T operator*(const VectorImpl& other) { return 0; }
protected:
std::array<T, dim> elements;
};
template <int dim, typename T = float>
class Vector : public VectorImpl<dim, T> {};
template<typename T>
class Vector<2, T> : public VectorImpl<2, T>
{
public:
T x() const { return this->elements[0]; }
T y() const { return this->elements[1]; }
};
template<typename T>
class Vector<3, T> : public VectorImpl<2, T>
{
public:
T x() const { return this->elements[0]; }
T y() const { return this->elements[1]; }
T z() const { return this->elements[2]; }
};
int main()
{
Vector<2> v;
Vector<3> vv;
v + v;
vv.z();
}
这篇关于混合部分模板专门化和默认模板参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!