We have the following Template function, which returns first n elements of the vector:
template <typename T>
vector <T> Head(vector <T>& v, size_t top) {
return {
v.begin (),
next(v.begin (), min(top , v.size ()))
};
}
If we using this function in the range-based for loop, we return the copy of the vector:
int main () {
vector <int> v = {1, 2, 3, 4, 5};
for (int x : Head(v, 3)) {
++x; //increasing each element by 1
}
for (int x : v) {
cout << x << " ";
}
}
My question is: why the copy of the vector is returned (from the Head function)? I would expect, that by accessing first 3 elements of the vector by reference (vector <T>& v
) we would change the original vector by increasing first three elements by 1. Instead, ++x
is done on the copy of the vector. Can you explain why is it happened?
The follow up question: why does changing first 3 elements of the vector works with template classes?
Example:
template <typename Iterator >
struct IteratorRange {
Iterator first , last;
Iterator begin () const {
return first;
}
Iterator end () const {
return last;
}
};
template <typename T>
IteratorRange <typename vector <T >:: iterator > Head(vector <T>& v, size_t top) {
return {
v.begin (), next(v.begin (), min(top , v.size ()))
}
Head
is defined to return a std::vector<int>
value. By the rules of the language that object is distinct from the vector v
.
Even though it was constructed using an iterator, any references the new object has to the original are lost after construction. The new vector does not store those. It is created as a copy. See the documentation for std::vector
constructors.
Your IteratorRange
class template, on the other hand, does store iterators and behaves as a sub-range wrapper to the original object that can be used in range-based loops even if you make copies of it.