Reputation: 117
I want to create a generic Vector class like this Vector<int Dimension, typename Type>
. And this is my code:
template <int Dimension, typename Type>
class Vector
{
public:
Vector()
: _data {}
{}
Vector(const std::array<Type, Dimension>& init)
: _data {init}
{}
...
protected:
std::array<Type, Dimension> _data;
};
With that declaration, i can initialize my vector with a std::array
.
Vector<3, float> vec({1.0f, 2.0f, 3.0f});
// or like this
Vector<3, float> vec = {{1.0f, 2.0f, 3.0f}};
But now i want my vector has a better constructor for some common vector type like Vec1, Vec2, Vec3, ... I have tried to create a recursion template class to add an additional constructor for each of them:
template <typename Type>
class Vector<3, Type>
{
public:
Vector(const Type& x, const Type& y, const Type& z)
: _data {x, y, z}
{}
};
But when i compile my program i received this error:
error C3861: '_data': identifier not found
My questtion are:
Vector
.PS: Sorry if my English is hard to understand 🤦♀️.
Upvotes: 2
Views: 193
Reputation: 119877
There is no recursion here. Vector<3, Type>
is a wholly independent thing, unrelated to the generic Vector<Dimension, Type>
. It does not contain any _data
or anything else that the main template contains.
You don't need recursion or specialisation here, you need a forwarding constructor.
template <int Dimension, typename Type>
class Vector
{
public:
template <typename ... T>
Vector(T&& ... t)
: _data{std::forward<T>(t)...} {}
protected:
std::array<Type, Dimension> _data;
};
This is the only constructor you need. It basically says "initialise Vector with whatever you can initialise _data". So you can have:
Vector<4, int> v4(1,2,3,4);
Vector<2, int> v2{1,2};
std::array<float, 3> u3 = {1.0, 2.0, 3.0};
Vector<3, float> v3{u3};
Vector<5, float> v5;
No. Perhaps you do need to add some functionality to Vector<3,Type>
which is not present in the main template. In this case you can use inheritance.
Rename your Vector
class template to VectorBase
Create a new Vector
class template that inherits from ``VectorBase` and uses its constructor, and does nothing more:
template <int Dimension, typename Type>
class Vector : public VectorBase<Dimension, Type> {
public:
using VectorBase<Dimension, Type>::VectorBase;
};
Now you can specialise Vector
and add functionality to it. You need to repeat the using
declaration in every specialisation, but that's not too much boilerplate.
Upvotes: 2