Take the following code:
std::vector<std::vector<int>> v(10, 10);
This code doesn’t compile with libstdc++. It does compile with Visual Studio’s C++ library, however. The behavior I would expect is that v is filled with 10 vectors of size 10, and this is what I get with Visual Studio.
The constructor invoked with Visual Studio is the one taking two iterators. The constructor itself is defined as:
template<class _Iter>
vector(_Iter _First, _Iter _Last)
: _Mybase()
{ // construct from [_First, _Last)
_Construct(_First, _Last, _Iter_cat(_First));
}
There are two versions of the template function _Construct. Both have the same signature, but one initializes the vector from a range, and the other initializes the vector with N copies of the value type copy constructed from the second parameter. In this case, the template parameters are only valid for the second version of _Construct.
The result is that v is filled with 10 copies of a vector that was copy constructed from the value 10. The same code path is taken by constructing it like this, as you would have to do for the same effect using libstdc++:
std::vector<int> temp(10);
std::vector<std::vector<int>> v(10, temp);
Which implementation is correct here? Is this a libstdc++ bug or an extension of Visual Studio’s C++ library?
Edit: Just to clarify, I’m not asking if it should be invoking the range constructor. I’m asking which C++ implementation has the correct behavior, regardless of which path it takes to achieve it.
This should not compile, because the vector’s single argument constructor is explicit.
C++03:
C++11:
This means a number like 10 can’t implicitly turn into a vector of size 10.