Mix partial template specialization with default template settings

I would like to create a common vector class and create specializations for several cases. Something like this (it does not compile, but hopefully connects 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 element type to be float , and I want to have access methods x() and y() for the case dim = 2 and x() , y() and z() for the case dim = 3 . I am a bit confused by the error messages:

vector.h: 56: 10: error: declaration 'int dim

vector.h: 6: 10: error: shadow pattern parm 'int dim

(same for T ).

How can I do it right? (if possible)

+6
source share
3 answers

1.

For a partial specialization of a template, specify only the template parameters, which are actually parameters. Since you already set dim as 2 or 3, there is no need to specify it again.

 template<typename T> class Vector<2, T> { .... 

2.

Specialization of a class really means changing the whole declaration. Therefore, the s members of the general Vector<dim, T> will not be available in the specialized Vector<2, T> . You can make a general Vector<dim, T> as in an internal base class and create a subclass for specialization only:

 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 do not need to define VecType ! Inside the template, you can simply use Vector . A call to the class with the correct parameters will be automatically displayed.

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(); } 
+10
source

Partial specialization should be something like this:

 template <int Dim, typename T = float> class Vector; // primary template <typename T> class Vector<2, T> { /* ... */ }; template <typename T> class Vector<3, T> { /* ... */ }; 
+2
source

You can do it as follows:

 #include <array> template<int dim, typename T = float> class Vector { public: typedef Vector<dim, T> VecType; Vector() { /**/ } Vector(const VecType& other) { /**/ } private: std::array<T, dim> elements; }; template<typename T> class Vector<2, T> { public: T x() const { return elements[0]; } T y() const { return elements[1]; } private: std::array<T, 2> elements; }; template<typename T> class Vector<3, T> { public: T x() const { return elements[0]; } T y() const { return elements[1]; } T z() const { return elements[2]; } private: std::array<T, 3> elements; }; int main(int argc, char **argv) { Vector<2> v2; v2.x(); Vector<3> v3; v3.z(); return 0; } 

This can be compiled in gcc 4.5.2 (do not run it ...).

However, this way you cannot use any of the member variables of the member function in your main specialization template.

0
source

Source: https://habr.com/ru/post/904535/


All Articles