c++ - How to parameterize the number of parameters of a constructor? -
i want accept number of parameters (this number being defined in template parameter) in template class constructor. can't use initializer_list, since can't assert size @ compile time, far know.
what tried
my first attempt using std::array parameter:
template<size_t s> class foo { int v[s]; public: foo(std::array<int, s>) {/*...*/} }; however, forces me initialize (even when constructor not explicit) :
foo<4> a{{1,2,3,4}} // 2 brackets. i think there may template magic (variadic templates?), can't figure out proper syntax use in constructor. can't call constructor recursively... can i?
i tried looking definition of constructor std::array(since doesn't allow more parameters size of array, want), find has implicit constructors. default constructors? if so, how does
std::array<int, 3> = {1,2,3} work?
optional bonus: why didn't standard define fixed size alternative std::initializer_list? std::static_initializer_list<t, n>. there plans on supporting kind of functionality in future? needed?
you create variadic constructor , assert provided right number of arguments:
template <size_t sz> struct foo { template <typename... args> foo(args... args) { static_assert(sizeof...(args) <= sz, "invalid number of arguments"); // ... stuff ... } }; so that:
foo<3> f; // ok foo<3> f(1, 2, 3); // ok foo<3> f(1, 2, 3, 4, 5); // error as example initialize array, like:
template <size_t sz> struct foo { template <typename... args> foo(args... args) : v{{args...}} { static_assert(sizeof...(args) <= sz, "invalid number of arguments"); } std::array<int, sz> v; }; that constructs v correctly you'd expect, though if try pass more sz args foo's constructor, you'd see error on initializing v before static_assert.
for clearer static_assert error, delegate top-level foo private constructors take integral_constant argument whether or not they're valid constructors:
template <typename... args> foo(args... args) : foo(std::integral_constant<bool, sizeof...(args) <= sz>{}, args...) { } private: template <typename... args> foo(std::true_type, args... args) : v{{args...}} { } template <typename false, typename... args> foo(false, args... ) { // false ever std::false_type static_assert(false::value, "invalid number of arguments!"); }
Comments
Post a Comment