Search code examples
c++arraysc++11initializer-list

no match for operator '=' (std::array<T, 3> and std::initializer_list<T>)


I have a template vec<T> class for math vectors with constant length is equal to 3. It looks like this:

template <typename T>
class vec{
public:
    vec() { /**/ }

    vec(std::initializer_list<T> list) { /**/ }

private:
    std::array<T, 3> data;
};

I know, that it is possible to initialize std::array with an std::initializer_list in such a way:

std::array<int, 3> a = {1, 2, 3};

So I would like to have a constructor with an std::initializer_list to initialize my vector like this:

vec<int> v = {1, 2, 3};

I also have a solution for this: just iterate through std::initializer_list elements and write to data:

vec(std::initializer_list<T> list) {
    size_t i = 0;
    for (auto it = list.begin(); it != list.end(); it++) {
        data[i++] = *it;
    }
}

I tried to make constructor look like this (because of std::array has a constructor with std::initializer_list):

vec(std::initializer_list<T> list) {
    data = list;
}

But when I try to compile a program, the error occurs:

no match for ‘operator=’ (operand types are ‘std::array<int, 3>’ and ‘std::initializer_list<int>)’

What's the problem here? Why can't I initialize std::array with initializer list in such a way?


Solution

  • Why can't I initialize std::array with initializer list in such a way?

    Braced-init-list and std::initializer_list are not the same thing. (Even std::initializer_list could be constructed from braced-init-list.) std::array is an aggregate and could be aggregate-initialized or assigned by braced-init-list as

    std::array<int, 3> a = {1, 2, 3};
    a = {4, 5, 6}; // convert {4, 5, 6} to std::array then assign to a
    

    Note that both {1, 2, 3} and {4, 5, 6} are braced-init-list but not std::initializer_list.

    std::array can't be initialized (or assigned) from an std::initializer_list; its constructors and assignment operator are implicitly-defined and doesn't have such constructor or assignment operator taking std::initializer_list.

    std::initializer_list<int> l = {1, 2, 3};
    std::array<int, 3> a = l; // doesn't work
    a = l;                    // doesn't work