Thursday, September 29, 2011

Initializer Lists in C++0x

In C++0x, there's a new language feature called initializer_list. In this post, we will see some hints about this helpful feature.
We have not a uniform initializing method in the previous C++ standards. For example:
int i = 0;
    int j(0);
    char a[6] = "C++0x"; // ={'C', '+', '+', '0', 'x'};
    Student s("Bjarne", "Stroustrup");

or
vector<int> v(5); // 5 items
    v.push_back(8);
    v.push_back(1);
    //other 3 items are 0

There are different styles of initilizing which is confusing programmers. So, a uniform initializing method would be great: Thanks to C++0x.
First, we will see some quick usages of this feature to warm up:
vector<int> v = {8, 1, 7, 9}; //see the difference in previous vector initialization
    list<string> cities = {"Ankara", "Istanbul", "Izmir"};
    int a[3][4] = {
        {0, 1, 2, 3},
        {4, 5, 6, 7},
        {8, 9, 10, 11}
    };

    void f(initializer_list<int> args) //This function takes an initializer list as argument(an immutable sequence)
    {
        for (auto p = args.begin(); p != args.end(); ++p) cout << *p << "\n";
    }
    f({1, 2}); // passing a list on the fly
    vector<double> v1
    {
        7
    }; // ok: v1 has 1 element (with its value 7)
    v1 = {9}; // ok v1 now has 1 element (with its value 9). how can we do that without initializer_list?
    // we should first clear the vector and then push '9' to the vector
    vector<double> v2 = {9}; // ok: v2 has 1 element (with its value 9)

Of course this new feature is widely used in standard library of C++0x. Here are two samples taken from GCC implementation of C++0x:

    * std::string class:

        In GCC implementation there's a new constructor that makes use of initializer_list,
#ifdef __GXX_EXPERIMENTAL_CXX0X__
    /**
     *  @brief  Construct string from an initializer list.
     *  @param  l  std::initializer_list of characters.
     *  @param  a  Allocator to use (default is default allocator).
     */
    basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc());
#endif // __GXX_EXPERIMENTAL_CXX0X__


    Let's create a string object with this new style constructor,
std::string s({'C', '+', '+', '0', 'x'});
    std::cout << s << "\n";

    Output:
        C++0x

    * vector class:
Assignment operator in vector class shows us how to use initializer_list,
#ifdef __GXX_EXPERIMENTAL_CXX0X__

    vector& operator=(initializer_list<value_type> __l) {
        this->assign(__l.begin(), __l.end());
        return *this;
    }
#endif // __GXX_EXPERIMENTAL_CXX0X__


    When we assign an initializer_list to the vector object, this operator=() function is called:
v1 = {9};

Analyzing the std::initializer_list implementation is a good work to understand the inner details.

Reference:
http://www2.research.att.com/~bs/C++0xFAQ.html#init-list