C++11
The program initializes a vector
, named myVec
, of int
vector
s, and then uses a loop to print out each inner vector
's elements. But I got unexpected results when trying to see what happens when I use extra curly braces. The following is also on this LiveWorkSpace for easy toggling between compilers. g++ 4.8.0
only compiles up to myVec[5]
. clang++ 3.2
compiles everything:
#include <iostream>
#include <vector>
int main()
{
std::vector<std::vector<int>> myVec =
{
/* myVec[0] */ {1, 2},
/* myVec[1] */ {},
/* myVec[2] */ {{}},
/* myVec[3] */ { {}, {} },
/* myVec[4] */ { {}, {}, {} },
/* myVec[5] */ {{{}}}
/* myVec[6] */ // , { {{}}, {{}} } // g++ 4.8.0 COMPILER ERROR
/* myVec[7] */ // , {{{{}}}} // g++ 4.8.0 COMPILER ERROR
/* myVec[8] */ // , { {{{}}}, {{{}}} } // g++ 4.8.0 COMPILER ERROR
};
// loop for printing
for (unsigned int i = 0; i < myVec.size(); ++i)
{
std::cout << "myVec[" << i << "]: ";
for (unsigned int j = 0; j < myVec.at(i).size(); ++j)
{
std::cout << myVec.at(i).at(j) << ", ";
}
std::cout << std::endl;
}
return 0;
}
Actual g++ 4.8.0
output:
myVec[0]: 1, 2,
myVec[1]:
myVec[2]: 0,
myVec[3]: 0, 0,
myVec[4]: 0, 0, 0,
myVec[5]: 0,
Analysis:
myVec[0]
: {1, 2}
:
Got expected output.
myVec[1]
: {}
:
Got expected output.
myVec[2]
: {{}}
:
This is a vector of the int
0
. The inner brace initializes an int
to 0
.
myVec[3]
: { {}, {} }
:
The two inner braces initializes an int
each to 0
.
myVec[4]
: { {}, {}, {} }
:
The three inner braces initializes an int
each to 0
.
myVec[5]
: {{{}}}
:
I wanted to add yet another set of curly braces to myVec[2]
to see how far I can go with adding braces before getting compiler errors. I don’t understand why this compiles and why its element prints as 0
.
For example, int j = {}
initializes j
to 0
. vector<vector<int>> v = { {{}} }
initializes the innermost {}
to int
0
, making it equivalent to vector<vector<int>> v = { {0} }
. Then, what is vector<vector<int>> u = { {{{}}} }
and why would it compile?
The Hypothetical myVec[6]
: { {{}}, {{}} }
:
Following the same pattern as above, I wanted to make a vector that contains two sets of double curly braces. But this doesn’t compile, and I don’t understand why this breaks the pattern of giving me multiple zeroes.
The Hypothetical myVec[7]
: {{{{}}}}
:
I wanted to add yet another set of curly braces to myVec[5]
to see how far I can go with adding braces before getting compiler errors. I don’t understand why this breaks the pattern and doesn't compile.
The Hypothetical myVec[8]
: { {{{}}}, {{{}}} }
:
I wanted to extend myVec[7]
to to make a vector with two sets of triple braces. I don't understand why this doesn't compile either.
If everything up to myVec[5]
compiles, why doesn't the rest?
Try to compile this code. it should explain your issue:
int i = {}; // initializes i to int()
int j = {{}}; // fails to compile
why {{{}}}
is accepted in your code seems to be a gcc bug(needs to clarify) related how ctor is processed:
struct foo {
foo( std::initializer_list<int> ) {}
};
void f()
{
foo bar1( {{{}}} ); // compiles fine
foo bar2 = {{{}}}; // compiles fine
}
Edit (thanks to Johannes Schaub) - deleting copy ctor makes first variant uncompilable:
struct foo {
foo( std::initializer_list<int> ) {}
foo( const foo& ) = delete;
};
void f()
{
foo bar1( {{{}}} ); // fails to compile: use of deleted function ‘foo::foo(const foo&)’
foo bar2 = {{{}}}; // still compiles, neither deleting move ctor, nor assignment operator does not affect that, is copy ctor of std::initializer_list involved?
}
for member function it fails:
struct foo {
void moo( std::initializer_list<int> ) {}
};
void f()
{
foo bar;
bar.moo( {{{}}} ); // fails to compile
}
This code fails as well:
std::initializer_list<int> l = {{{}}}; // fails to compile
Same situation ctor vs member function for std::vector:
void f()
{
std::vector<int> v( {{{}}} ) // compiles fine;
v.assign( {{{}}} ); // fails to compile
};
gcc version 4.7.2 (Ubuntu/Linaro 4.7.2-2ubuntu1)