c++ - Compile time checking for the number of arguments in a variadic template -
i made generic n-dimensional array class, want make safer compile-time checks.
the constructor , operator()
expected work correctly when number of arguments given equals dimension
. still, if write code like
array<int, 2> a(1, 2, 3); //3 dimensions 2d array == crash
or
array<int> a(1); //plain 1d array std::cout << a(1, 2); //segfault
it silently compiles, , need run debugger, it's quite confusing debug variadic templates.
can think of way provide compile time check correct number of arguments matching dimension?
template<typename t, int dimension = 1> class array { private: std::unique_ptr<t[]> pointer; int size[dimension]; int realsize; public: array() { } template<typename... ns> array(ns... ns) : realsize(1) { create(1, ns...); } private: template<typename... ns> void create(int d, int n, ns... ns) { realsize *= n; size[d - 1] = n; create(d + 1, ns...); } void create(int d) { pointer = std::unique_ptr<t[]>(new t[realsize]); } int computesubsize(int d) const { if (d == dimension) { return 1; } return size[d] * computesubsize(d + 1); } template<typename... ns> int getindex(int d, int n, ns... ns) const { return n * computesubsize(d) + getindex(d + 1, ns...); } int getindex(int d) const { return 0; } public: template<typename... ns> t& operator()(ns... ns) const { return pointer[getindex(1, ns...)]; } int getsize(int d = 1) const { return size[d - 1]; } };
you can add compile time assert statements @ right places prevent code like
array<int, 2> a1(1, 2, 3);
and
array<int> a3(1); std::cout << a3(1, 2);
from being compiled.
here's once place:
template<typename... ns> array(ns... ns) : realsize(1) { static_assert(sizeof ...(ns) == dimension, "incorrect number of arguments"); create(1, ns...); }
that prevents line
array<int, 2> a1(1, 2, 3);
from being compiled.
another place:
template<typename... ns> t& operator()(ns... ns) const { static_assert(sizeof ...(ns) == dimension, "incorrect number of arguments"); return pointer[getindex(1, ns...)]; }
that prevents
array<int> a3(1); std::cout << a3(1, 2);
from being compiled.
here valid statements:
array<int, 2> a2(1, 2); array<int> a3(1); std::cout << a3(0);
Comments
Post a Comment