混合部分模板专门化和默认模板参数 [英] Mixing partial template specialization and default template parameters

查看:117
本文介绍了混合部分模板专门化和默认模板参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个通用的向量类,并为几种情况创建专门化。这样的东西(它不编译,但希望传达我的意图):

 模板< 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆