Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assigning a braced-init-list to STL containers in C++11

I've noticed that, in addition to initialization, I'm able to assign initializer lists to STL containers such as std::array and std::vector. For example:

#include <iostream>
#include <array>
#include <vector>
using namespace std;

int main()
{
    array<int, 4> arr;
    vector<int> vec(4);

    arr = {{1, 2, 3, 4}};
    vec = {4, 3, 2, 1};

    cout << "arr: ";
    for (auto elem : arr)
        cout << elem << " ";

    cout << "\nvec: ";
    for (auto elem : vec)
        cout << elem << " ";
    cout << endl;
}

I'm compiling this code on Clang 3.8.0 with just the -std=C++11 flag. I'm trying to discern whether this behavior is defined by the C++11 standard, or just the compiler. I've been trying to make my way through the relevant parts of the standard (and cppreference.com when the language in the standard gets too complex) and so far have come up with this:

Initializer Lists

5.17.9 - a brace-init-list may appear on the right hand side of an assignment defined by a user-defined assignment operator

std::array

23.3.2.2: class array relies on implicitly-declared special member functions ... to conform to container requirements

std::vector

vector& operator=( std::initializer_list ilist );

  • Replaces the contents with those identified by initializer list ilist. (Since C++11)

From the syntax of the overloaded assignment operator for std::vector it seems clear that assignment by an initializer list is supported. So I'm wondering if passing an initializer list to the overloaded assignment operator implicitly defined for STL containers (std::array in my example) is defined behavior? As a bonus, is std::array the only STL container with an implicitly defined overloaded assignment operator?

I've looked at answers to related questions on SO such as:

how to assign an array from an initializer list

Error: Assigning to an array from an initializer list

However the answers given do not coincide with behavior I'm getting from my compiler, or what I'm interpreting from the standard. Also, I'm looking for an answer to a more general question than just assigning list initializers to std::array.

like image 266
digilur Avatar asked Mar 06 '23 14:03

digilur


2 Answers

See defect #1527, which changed the wording in [expr.ass]/9 from "an assignment defined by a user-defined assignment operator" to "an assignment to an object of class type" - that is, the operator doesn't have to be user-defined. I assume the compiler you use has implemented the resolution for this defect.

std::array has implicitly-defined copy-assignment operator=(const std::array&) - that's the one being called, with argument being a std::array temporary constructed via aggregate initialization.

like image 58
Igor Tandetnik Avatar answered Mar 11 '23 11:03

Igor Tandetnik


There is no assignment operator defined for std::array which accepts an initializer_list.

However the argument of the implicitly defined assignment operator (which is an std::array itself) can be constructed from an initializer list. And this is exactly what happens here.

Note that this doesn't work for built-in arrays, those cannot be assigned at all.

like image 45
n. 1.8e9-where's-my-share m. Avatar answered Mar 11 '23 09:03

n. 1.8e9-where's-my-share m.