I am implementing my static multi-dimentional vector class. I am using std::array
as the underlying data type.
template <typename T, std::size_t N>
class Vector {
private:
std::array<T, N> data;
};
I want to make my class downwards-compatible, so I am writing this:
template <typename T, std::size_t N>
class Vector : public Vector<T, N-1>{
private:
std::array<T, N> data;
};
template <typename T>
class Vector<T, 0> {};
My goal is that when one instance is used in downwards-compatible mode, its underlying data should be able to be reliably accessed:
template<typename T, std::size_t N>
T& Vector<T, N>::operator[](int i) {
// Do boundary checking here
return this->data[i];
}
void foo(Vector<int, 3>& arg) {
arg[1] = 10;
}
Vector<int, 5> b;
foo(b);
// Now b[1] should be 10
There are two points here:
Vector<T, 5>
should be accepted by foo()
, Vector<T, 2>
should be rejected.b[0]
through b[2]
in foo()
should pertain. b[3]
and b[4]
should not be accessible in foo()
.How can I achieve that?
How about a simple read wrapper around std::array<>
itself?
template<typename T, std::size_t N>
struct ArrayReader {
public:
// Intentionally implicit.
template<std::size_t SRC_LEN>
ArrayReader(std::array<T, SRC_LEN> const& src)
: data_(src.data()) {
static_assert(SRC_LEN >= N);
}
private:
T const* data_;
};
void foo(ArrayReader<float, 3>);
void bar() {
std::array<float, 4> a;
std::array<float, 2> b;
foo(a);
foo(b); //BOOM!
}
Of course, you can easily substitute std::array
for your own type, this is just an example of the principle.