I am using std::array
(N is a fixed template-variable).
#include
template
struct A{
size_t fun
You can create a wrapper for your objects
template <class T>
struct WrapT
{
WrapT() = delete;
WrapT(T e) : value(e){}
public: T value;
// or add some operator()
};
and
size_t function(std::array<WrapT<size_t>, N> arr){ return arr[N-1].value;}
so a function call like (with full brace-init)
function({ {{1}, {2}, {3}, {4}} });
will not compile because of use of deleted function. Live example. The syntax is a little clumsy, and even then I'm not sure all the possible value-initialization cases are covered.
@dpy points out you may omit the innermost ones, so you get to your original code: function( {{ 1, 2, 3, 4, 5 }} )
.
Simple answer: You cannot.
When initializing std::array
with a list, it is doing an aggregate initialization
, and it is explained here when the list size is less than the number of member:
It is simply a legal and acceptable behavior to provide less than the size list, so compiler will not complain anything. Your code:
A<5> a;
a.function({{1,2,3}}));
is equivalent to:
A<5> a;
a.function({{1,2,3,0,0}}));
to compiler. Your best bet is runtime error (which may not be as you wished).
You can enforce this by using parameter pack, but with a bit different syntax:
#include <array>
template<size_t N>
struct A{
template<typename... T>
size_t function(T&&... nums)
{
static_assert(sizeof...(nums) == N, "Wrong number of arguments");
std::array<size_t, N> arr = { std::forward<size_t>(nums)... };
return arr[N-1];
}
};
int main(){
A<5> a;
a.function(1,2,3,4,5); // OK
a.function(1,2,4,5); // Compile-time error
}
But, I think there is no good way to enforce that in compile time. I would just use assert(il.size() == N)
in production code to check size of initializer list.