6

I want to write a math vector template. I have a class which accepts type and size as template argument, with a lot of math operation methods. Now I want to write specializations where Vector<3> for instance has x, y, z as members which refer to data[0..3] respectively.

The problem is that I don't know how to create a specialization which inherits everything from the default template without creating either a base class or writing everything twice.

What's the most efficient way to do this?

template<class Type, size_t Size> class Vector { // stuff }; template<class T> class Vector<3,T>: public Vector { public: T &x, &y, &z; Vector(): Vector<>(), x(data[0]), y(data[1]), z(data[2]){} // and so on }; 
1
  • 3
    Creating a base class is the typical approach there. Commented Oct 16, 2012 at 21:47

2 Answers 2

7

Somehow you should be able to derive from default implementation, but you are specializing an instance, so how? it should be a non-specialized version that you can be able to derive from it. So that's simple:

// Add one extra argument to keep non-specialized version! template<class Type, size_t Size, bool Temp = true> class Vector { // stuff }; // And now our specialized version derive from non-specialized version! template<class T> class Vector<T, 3, true>: public Vector<T, 3, false> { public: T &x, &y, &z; Vector(): Vector<>(), x(data[0]), y(data[1]), z(data[2]){} // and so on }; 
Sign up to request clarification or add additional context in comments.

6 Comments

While this works nicely, it seems a bit clunky (to me) to have an internal template parameter in an external interface.
User never use this extra template parameter, of course you have another option that both specialized and default implementation derive from a base class that contain actual implementation! but in my opinion that's a bit harder than this technique!
@Cameron all class interfaces show private data members as well. Needed for size calculation, but still. I think this justifies it, since it is never needed from outside.
Okay, it does not work that easily. When I return a Vector in the base class it is type Vector<3,double,true> which means it is not compatible to Vector<3,double,false> (which the subclass is). I'll check if casting works.
@weltensturm You can create your own cast is just piece of cake! Vector(Vector<T, S, Temp> const& rhs) and Vector(Vector<T, S, !Temp> const& rhs)
|
1

Consider making this in a little different way, but goals will be achieved, Add external interface - I mean standalone functions X(), Y(), Z():

template<class T, size_t S> T& x(Vector<T, S>& obj, typename std::enable_if<(S>=1)>::type* = nullptr) { return obj.data[0]; } template<class T, size_t S> T& y(Vector<T, S>& obj, typename std::enable_if<(S>=2)>::type* = nullptr) { return obj.data[1]; } template<class T, size_t S> T& z(Vector<T, S>& obj, typename std::enable_if<(S>=3)>::type* = nullptr) { return obj.data[2]; } 

There is no big difference between:

 Vector<T, 3>& obj return obj.x(); 

And

 Vector<T, 3>& obj return x(obj); 

As a bonus - this interface works for matching sizes.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.