How do I initialize a member array with an initializer_list?

swestrup picture swestrup · Apr 5, 2011 · Viewed 39.7k times · Source

I'm getting up to speed with C++0x, and testing things out with g++ 4.6

I just tried the following code, thinking it would work, but it doesn't compile. I get the error:

incompatible types in assignment of ‘std::initializer_list<const int>’ to ‘const int [2]’

struct Foo
  {
    int const data[2];

    Foo(std::initializer_list<int const>& ini)
    : data(ini)
    {}
  };

Foo f = {1,3};

Answer

JohannesD picture JohannesD · Apr 5, 2011

You can use a variadic template constructor instead of an initializer list constructor:

struct foo { 
    int x[2]; 
    template <typename... T> 
    foo(T... ts) : x{ts...} { // note the use of brace-init-list
    } 
};

int main() {
    foo f1(1,2);   // OK
    foo f2{1,2};   // Also OK
    foo f3(42);    // OK; x[1] zero-initialized
    foo f4(1,2,3); // Error: too many initializers
    foo f5(3.14);  // Error: narrowing conversion not allowed
    foo f6("foo"); // Error: no conversion from const char* to int
}

EDIT: If you can live without constness, another way would be to skip initialization and fill the array in the function body:

struct foo {
    int x[2]; // or std::array<int, 2> x;
    foo(std::initializer_list<int> il) {
       std::copy(il.begin(), il.end(), x);
       // or std::copy(il.begin(), il.end(), x.begin());
       // or x.fill(il.begin());
    }
}

This way, though, you lose the compile-time bounds checking that the former solution provides.