c++ – Curly initialization std::vector: multiple nested braces

Question:

This code compiles:

#include <vector>

int main(int argc, char* argv[])
{
  std::vector<int> v2 = { { {} } };
  std::vector<int> v3 { { {} } };
  std::vector<int> v4 { { { 1 } } };
  std::vector<int> v5 ({ { { 1 } } });

  return 0;
}

Why? How are multiple curly braces interpreted? If there was one pair of parentheses, it would be the initializer_list. And what are the three pairs of parentheses converted to? And why exactly three and not more (in GCC)? (Visual Studio 2013 allows an arbitrary number of parentheses in this situation.)

Answer:

All variants use the std::vector<int> constructor, which initializes it from std::intializer_list<int> , and the fourth alternative then uses the vector copy constructor.

In this case, the presence or absence of = in the syntax of the initialization sheet in the first three options does not play a role, i.e. there is no difference in the semantics of the first two options.

  1. Option

     std::vector<int> v2 = { { {} } };

    similar

     std::intializer_list<int> temp_list = { {} }; std::vector<int> v2 = { temp_list };

    In this case, {} is a valid initializer for an object of type int , i.e.

     std::intializer_list<int> temp_list = { {} };

    in turn, similarly simply

     int temp_int = {}; // инициализация нулем std::intializer_list<int> temp_list = { temp_int };
  2. Option

     std::vector<int> v3 { { {} } };

    this, as mentioned above, is the same, only in the direct sheet-initialization syntax.

  3. In the variant

     std::vector<int> v4 { { { 1 } } };

    { 1 } is a perfectly valid initializer for an object of type int . Those. this option is the same

     int temp_int = { 1 }; std::intializer_list<int> temp_list = { temp_int }; std::vector<int> v4 = { temp_list };
  4. And here is an option

     std::vector<int> v5 ({ { { 1 } } });

    already uses the copy constructor of the std::vector<int> class, i.e. similar

     std::vector<int> temp_vector = { { { 1 } } }; // см. вариант 3 std::vector<int> v5(temp_vector);

    For example, if we declare an artificial class

     struct S { S(std::initializer_list<int> l) {} S(const S&) = delete; };

    then the first three options will compile perfectly for it, but the fourth one will refuse to compile due to the remote copy constructor.

Attempts to increase the number of brackets lead to the formation of an incorrect initializer at the lowest level: neither { {} } nor { { 1 } } are already valid initializers for an object of type int . So the code doesn't compile. By the way, VS2015 also refuses to compile options with an increased number of brackets.

Scroll to Top