DarthRubik
DarthRubik

Reputation: 3975

std::array Type Initialization

With a std::array you can initialize it like this:

std::array<int,5> myArray = {1,2,3,4,5};

If I where trying to create my own array class how would I do something similar?

Upvotes: 2

Views: 97

Answers (2)

Holt
Holt

Reputation: 37606

std::array rely on aggregate initialization (the C way of initializing struct), basically this is valid c++:

struct A {
    int values[2];
    size_t size;
};

A a = {{42, 44}, 2U}; // No constructor involved
//     |         |--- a.size
//     |--- a.values

Now if you remove the size attribute, you get:

struct A {
    int values[2];
};

A a = {{42, 44}}; // Valid!

But c++ gives you something called brace-elision we allow you to omit the inner brackets, so:

A a = {42, 44}; // Still valid!

Now, just makes A a template:

template <typename T, size_t N>
struct A {
    T data[N];
};

A<int, 2> a = {{42, 44}};

Note that this does not makes use of initializer_list which are used for std::vector, std::list, and so on.

Also note that:

A<int, 2> a1{42, 44}; // Not valid prior to c++14
A<int, 2> a2{{42, 44}}; // Ok even for c++11

And note that clang will throw warning whatever the version you use by default.


A minimalist version of std::array could look like this:

template <typename T, size_t N>
struct my_array {

    T _data[N];

    T& operator[] (size_t i) { return _data[i]; }
    const T& operator[] (size_t i) const { return _data[i]; }

    constexpr size_t size () const { return N; }

    T* begin () { return _data; }
    const T* begin () const{ return _data; }
    T* end () { return _data + size(); }
    T* end () const { return _data + size(); }

};

Please note that the standard std::array has a lot more stuff than this (a lots of typedefs, other methods, a lots of overloads, ...), but this is a small base to get you started.

Also note that _data has to be public so that aggregate initialization can work (it does not work if you have private / protected members!).

Upvotes: 4

Rakete1111
Rakete1111

Reputation: 48928

Here is a simple implementation that supports initializing with a list of elements:

//template class 'array' takes 'T' (the type of the array) and 'size'
template<typename T, std::size_t size>
class array
{
public:
    //This is the concept of initializer lists (wrapper around variadic arguments, that
    //allows for easy access)
    array(std::initializer_list<T> list)
    {
        //Loop through each value in 'list', and assign it to internal array
        for (std::size_t i = 0; i < list.size(); ++i)
            arr[i] = *(list.begin() + i); //list.begin() returns an iterator to the firsts
                                          //element, which can be moved using +
                                          //(deferenced to get the value)
    }

    //Overloads operator[] for easy access (no bounds checking!)
    T operator[](std::size_t index)
    {
        return arr[index];
    }
private:
    T arr[size]; //internal array
};

You can then use it like so:

array<int, 2> a = { 2, 5 };
int b = a[0]; //'b' == '2'

Upvotes: 1

Related Questions