I have a situation where I need to pass in a variable number of integers (known at compile time).
I need to achieve something like this:
template <unsigned N>
void myFunc(std::array<int, N> values)
{
// Do something useful with the values
}
I hoped the above would work and could be called like this, conveniently without creating a temporary object;
myFunc<4>({1, 2, 3, 4});
This did in fact work, but the problem is that this also works...
myFunc<4>({1, 2});
which of course leaves two of the values uninitialised, unbeknownst to me and the user.
I believe this would work:
template <unsigned N>
void myFunc(std::vector<int> values)
{
assert(values.size() == N);
// Do something useful with the values
}
myFunc<4>({1, 2}); // Goes bang
myFunc<4>({1, 2, 3, 4}); // OK
Unfortunately I can't allocate memory in my environment), so I have to do everything on the stack (and can't just accept a vector of which I could check the size).
I see myself as having two options.
std::array<int, 4> arr{ 0, 1};
is fine; the elements that aren't specified are simply zero-initialized. If you don't want this to work, std::array
isn't the right class to use for you (or to be more precise: you cannot have it impose the desired restrictions).
You could of course create a variadic template and restrict the parameters according to your requirements:
template<size_t N, std::convertible_to<int>...Args>
requires (sizeof...(Args) == N)
void f(Args&&...args)
{
std::array<int, N> values{args...};
for (auto e : values)
{
std::cout << e << '\n';
}
}
...
f<4>(1, 2, 3, 4);
Why specify the number of elements multiple times though? Just use C++17's functionality doing CTAD and deduce the template parameter of the function based on the argument type:
template<size_t N>
void f2(std::array<int, N> const& values)
{
for (auto e : values)
{
std::cout << e << '\n';
}
}
...
f2(std::array{ 1, 2, 3, 4 });
or avoid the necessity of using a template by simply using an std::initializer_list<int>
as function parameter:
void f3(std::initializer_list<int> values)
{
for (auto e : values)
{
std::cout << e << '\n';
}
}
...
f3({ 1, 2, 3, 4 });