Search code examples
arraysc++11initializationstdarray

Is there a way to enforce full initialization of std::array


I am using std::array<size_t, N> (N is a fixed template-variable).

#include<array>
template<size_t N>
struct A{
   size_t function(std::array<size_t, N> arr){ return arr[N-1];} // just an example
};

int main(){
   A<5> a;
   a.function({{1,2,3,4,5}}));
}

And it works fine. The problem is that this other code is silently allowed:

   A.function({{1,2,3}}));

That is, even with missed elements the array is initialized somehow, even if it is well defined (e.g. remaining elements initialized to zero, I am not sure) this is a possible source of errors.

Is there a way to enforce the initialization of the extra elements? E.g. by generating a compiler error or a warning.

One option that I contemplated is to use initializer_list

   size_t function2(std::initializer_list<size_t> il){ assert(il.size() == N); ...}

The problem is that this generated a runtime error at best and a check in every call. I would prefer a compiler error/warning.

I am not so much bothered by the default initialization of std::array<>{} but by the incomplete initialization. (Maybe there is nothing it can be done about it, since this is inherited from the behavior of T[N] static array.)

I tried using clang 3.5 and gcc 5.


Solution

  • 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:

    • If the number of initializer clauses is less than the number of members or initializer list is completely empty, the remaining members are initialized by their brace-or-equal initializers, if provided in the class definition, and otherwise (since C++14) by empty lists, which performs value-initialization. If a member of a reference type is one of these remaining members, the program is ill-formed (references cannot be value-initialized)

    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).