相关文章推荐
苦闷的围巾  ·  const (C++) | ...·  2 月前    · 
谈吐大方的跑步鞋  ·  Errno 9: Bad file ...·  8 月前    · 
欢乐的熊猫  ·  java - What does JVM ...·  1 年前    · 
爱运动的青椒  ·  Spring ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

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)

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>

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 { ... }

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();
                Regarding #2, request for clarification.  Your text reads: You could make the generic Vector<dim, T> as into a private base class...  The example code uses public base class.  Is this intentional or accidental?  I suppose both cases are actually interesting and worthy -- private vs protected vs public inheritance for partial template specialisation.
– kevinarpe
                May 17, 2015 at 12:39
                @kevinarpe: I meant an "internal" base class which is not supposed to be referred directly out of the library (Edited). The base class needs to be public otherwise all methods in it are not accessible outside of the class.
– kennytm
                May 17, 2015 at 14:04
                I think it is possible to use private or protected inheritance, but using statements are required to 'elevate' the access of members to public.
– kevinarpe
                May 18, 2015 at 3:58

The 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> { /* ... */ };
                in 14.5.5/1 : "The template parameter list of a specialization shall not contain default template argument values."
– fefe
                Dec 27, 2011 at 13:59
    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 compile in gcc 4.5.2 (Don't run it ...).

However, in this way, you will not be able to use any of the member variable of member function define in your main template in the specialization.

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.