STL loses iterator category when range iterators are passed to vector constructor. Consider the following code:
#include <ranges>
#include <vector>
namespace sr = std::ranges;
namespace rv = sr::views;
template<sr::random_access_range Range>
auto to_vector(Range &&range)
{
return std::vector<sr::range_value_t<Range>>{sr::begin(range), sr::end(range)};
}
int main()
{
std::vector a{ 1,2,3,4,5 };
auto b = to_vector(a | rv::transform([](auto v) { return static_cast<float>(v); }));
}
Currently STL containers lack constructors accepting ranges. The above snippet, while explicitly requiring random access range (according to definition, a random access range "specifies a range whose iterator type satisfies random_access_iterator") eventually invokes vector's _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) instead of _Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag), losing iterator category(?). This in turn calls emplace_back in a loop, not preallocating vector storage.
On the other hand, calling to_vector and passing a correctly dispatches to forward_iterator_tag version.
STL version
Microsoft Visual Studio Professional 2019 Preview
Version 16.9.0 Preview 5.0
STL loses iterator category when range iterators are passed to vector constructor. Consider the following code:
Currently STL containers lack constructors accepting ranges. The above snippet, while explicitly requiring random access range (according to definition, a random access range "specifies a range whose iterator type satisfies random_access_iterator") eventually invokes vector's
_Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag)instead of_Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag), losing iterator category(?). This in turn callsemplace_backin a loop, not preallocating vector storage.On the other hand, calling
to_vectorand passingacorrectly dispatches toforward_iterator_tagversion.STL version