bakkaa
bakkaa

Reputation: 683

How to initialize a class like std::array

I'm trying to write a container class for vector arithmetic. The objects are static in size:

template<typename T, unsigned N>
class vec{
    T data[N] = {0};
public:
    vec(std::initializer_list<T> ini){
        std::copy(ini.begin(), ini.end(), data);
    }
}

This is how far I got.

But than I tested the std::array class for comparison and I noticed that it somehow could make a static assertion if the initializer list was to long or to short.

std::array<float, 2> a = {1, 2, 3, 4} <- instant error message from the visual studio ide

In my class I would have to check the length of the initializer list at run-time.

I assume, that the std::array class somehow manages it to directly initialize the data with the initializer list notation without the std::initializer_list class.

Is it possible to initialize my class in the same way as std::array?

Upvotes: 2

Views: 205

Answers (1)

Shafik Yaghmour
Shafik Yaghmour

Reputation: 158459

std::array is an aggregate and so it uses aggregate initialization. Providing excess elements during aggregate initialization is ill-formed and requires a diagnostic. The compiler at minimum has to provide a warning, both gcc and clang make this an error. So if you make your class an aggregate then you can have it work the same way std::array does. Note, in class member initializers makes your class a non-aggregate in C++11 but not in C++14.

We can see it is an aggregate by going to the draft C++11 standard section 23.3.2.1 [array.overview]:

An array is an aggregate (8.5.1) that can be initialized with the syntax

array<T, N> a = { initializer-list };

where initializer-list is a comma-separated list of up to N elements whose types are convertible to T.

and section 8.5.1 [dcl.init.aggr] covers aggregate intialization and says:

An initializer-list is ill-formed if the number of initializer-clauses exceeds the number of members or elements to initialize.

The draft standard provides for exposition a possible implementation which shortened to the bare minimum looks like this:

template <class T, size_t N>
struct array {
    T elems[N];
};

and the draft standard has a note which says:

The member variable elems is shown for exposition only, to emphasize that array is a class aggregate. The name elems is not part of array’s interface

which is an aggregate and will with both gcc and clang provide an error if excess elements are provided.

Also see What are Aggregates and PODs and how/why are they special?.

Upvotes: 2

Related Questions