I have created a maths library that operates via templates, it allows the user to specify the size and type of the array within a class which is then used to create a maths vector of any dimension up to four. As soon as I went to create a colour class, it struck me how similar the vector and colour class are. Is there anyway in which I could reduce code reuse and use some form of inheritance or specialisation to separate:
- Specific functionality (ie vector3 does not have a setXYZW() function, instead only a setXYZ()) to the dimension of which it can only be used in.
- Colour class and vector class can both (in terms of array data member) be of size ranging from 1 to 4 and the both share the same operators, but differ in their use in some circumstances such as a multiply vector differs from a multiply colour.
My knowledge of templates is not that good, so I would very much appreciate if anyone can show me the best solution to such a situation?
template < std::size_t N = 3, typename T = float >
class Vector
{
typedef T Degree, Radian;
private:
T m_vecEntry[N];
public:
// arithmetic operations
Vector operator + (const Vector & _vector) const;
Vector operator - (const Vector & _vector) const;
Vector operator * (const Vector & _vector) const;
Vector operator * (float _val) const;
};
template < std::size_t N = 4, typename T = float >
class Colour
{
private:
T m_colEntry[N];
public:
// arithmetic operations
Colour operator + (const Colour& _colour) const;
Colour operator - (const Colour& _colour) const;
Colour operator * (const Colour& _colour) const;
Colour operator * (float _val) const;
};
Your classes have a fair amount of duplicated code, it is advisable that you do something about it. A possible solution follows.
First, you take the common functionality to a base class:
Then you derive from it your
VectorandColourclasses. In each derived class you useusing Base::operation;to state explicitly that the corresponsing operation from the base class makes sense in the derived class.For operations that don’t make sense in the derived class you provide an alternative definition or not provide it at all (it will not be accessible since you didn’t write
using).You can also add operations that were not in the base class, like
Vector::norm:The only trick in this code is that I’ve used the CRTP to make base class operations work with derived types.
Here is a little test program:
It prints: