C++: Initializer lists

If developers want to declare and initialize an array of five integers, they can do something like:

int a[] = { 10, 20, 5, 45, 22 };

But before C++11, what used to happen when developers wanted to do the same thing using a container available in the standard library, like std::vector<T>? Something like:

std::vector<int> a = { 10, 20, 5, 45, 22 };

Exactly!!! The code would not compile. Initializer lists were only available for (as Marcin Łoś mentions in the comments section below) aggregate types… And then C++11 was published! :)

As mentioned, starting in C++11, the code shown above is perfectly valid and works as expected; that’s because C++11 introduced support for initializer lists for any data type.

So, the next question would be… How can a developer create their own classes that support these initializer lists?

The answer: The standard library includes a new template class called std::initializer_list<T>. When the compiler finds a declaration with an initialization similar to the one shown above { 1, 2, 3, 4, 5 };, it looks for a constructor that accepts an std::initializer_list<T> as an argument. If found, the compiler creates an instance of the that class, passing the values inside the curly brackets, and invokes the constructor.

The std::initializer_list<T> object can be iterated using a standard iterator.

The example shown below is a wrapper around a vector that implements support for std::initializer_list<T>:

#include <vector>
#include <initializer_list>
  
template <typename T>
class MyList
{
  private:
    std::vector<T> _items;
 
  public:
    MyList() { }
 
    MyList(const std::initializer_list<T>& x)
    {
      for (auto i = x.cbegin(); i != x.cend(); ++i)
        _items.push_back(*i);
    }
};

With this implementation, an instance of MyList can be created in this way:

MyList<int> x = { 10, 20, 1, 4, 8, 16, 9 };
MyList<std::string> y = { "hello", "world", "of", "c++", "programmers"};

3 thoughts on “C++: Initializer lists

  1. I really enjoy your C++11 articles :)
    This one contains, however, a minor mistake. In C++03, initializer lists were available for ‘aggregate’ types, not only built-ones. ‘Aggregate type’ is an array, or a class satysfying certain restrictions (has no user-declared ctor, no non-public non-static data, no base classes and no virtual functions).

      1. The most significant difference between these two is that POD’s member types are severely restricted, while aggregate can contain pretty much anything.
        Precisely, POD struct/union is an aggregate satisfying following conditions:
        – has no user-defined copy-assigmnent operator
        – has no user-defined destructor
        – has no non-static member being non-POD, array-of-non-POD or reference

        For longer description of these concepts (aggregate, POD) see: http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special/4178176#4178176
        (this post is not mine)

        Note: these are C++03 definitions, current (C++11) definitions are slightly altered to accomodate new concepts.

Leave a comment