Reputation: 575
I have a function which needs to divide a vector up into n sub-vectors. For example, it might look something like this:
void foo(std::vector<uint8_t> vec, int numSubVectors){
size_t size = vec.size() / numSubVectors;
auto iter = vec.begin();
for (int i = 0; i < numSubVectors; ++i) {
auto sub_vec = std::vector<uint8_t>(iter, iter + size);
// do something with sub_vec
// ...
iter += size;
}
}
I need this to work when called with foo({}, 1)
, where sub_vec gets assigned an empty vector on the first (and only) iteration of the loop.
I'm concerned about the std::vector<uint8_t>(iter, iter + size)
. Does the c++ standard allow a vector to be constructed using its range constructor when first == last?
According to cplusplus.com, "The range used is [first,last), which includes all the elements between first and last, including the element pointed by first but not the element pointed by last", but that statement doesn't make any sense when first == last?
I tried running it on an online IDE and it seems to work (https://ideone.com/V9hylA), so it's clearly not prohibited, but is it undefined behaviour?
Upvotes: 1
Views: 2107
Reputation: 81
From iterator.requirements.general of the standard:
An iterator and a sentinel denoting a range are comparable. A range [i, s) is empty if i == s; otherwise [...]
So when first == last, the standard explicitly defines this as an empty range.
Upvotes: 3
Reputation: 18652
The iterator pair [first, last)
where first == last
is how we define an empty range. It's syntactically and logically valid. Constructing a std::vector
from that iterator pair will do the correct thing and create an empty container.
Upvotes: 2