Reputation: 1014
Out of curiosity!
What can you do with the returning iterator
of std::generate_n
?
Return value :
Iterator one past the last element assigned if
count > 0
, first otherwise.
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto iterator = std::generate_n(std::back_inserter(v), 10, [&]() {return j++;});
std::cout << "type: " << typeid(iterator).name() << '\n';
/*
for (iterator = v.begin(); iterator< v.end(); iterator++){
std::cout << *iterator << " " << endl;
}
*/
for(auto a : v)
std::cout << a << " ";
std::cout << std::endl;
Output:
type: St20back_insert_iteratorISt6vectorIiSaIiEEE
1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5 6 7 8 9
iterator
shows a few member functions, but they are mostly operators.
Upvotes: 4
Views: 232
Reputation: 23822
What can you do the returning
iterator
ofstd::generate_n
?
You can use it to insert elements into your container.
Given that std::generate_n
returns a std::back_insert_iterator
, as defined in std::back_insert_iterator:
std::back_insert_iterator is a LegacyOutputIterator that appends to a container for which it was constructed. The container's
push_back()
member function is called whenever the iterator (whether dereferenced or not) is assigned to. Incrementing thestd::back_insert_iterator
is a no-op.
Effectively what your code is doing is appending 10 more int
s to the std::vector
. I would imagine j
is initialized with 0
, if it's not, you may be invoking undefined behavior.
Return value:
Iterator one past the last element assigned if
count > 0
, first otherwise.
It's always pointing to one past the last element where a new element should be inserted, if the container is empty, it will be pointing to the first element of the container, which, again, is where the new element should be inserted.
Example:
iterator = 25;
Will append 25
to the vector, your output will be:
1 2 3 4 5 6 7 8 9 10 0 1 2 3 4 5 6 7 8 9 25
Upvotes: 3
Reputation: 122830
Suppose you want to generate elements for the first half and then use a different generator for the second half, then you can simply write:
#include <vector>
#include <algorithm>
#include <iostream>
int main() {
int j = 0;
std::vector<int> v{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto iterator = std::generate_n(v.begin(), 5, [&]() {return j++;});
std::generate_n(iterator,5,[&](){ return j;});
for (auto i : v){
std::cout << i << " ";
}
}
Without manually calculating the iterator
that points to the element after the ones from the first call.
Output is:
0 1 2 3 4 5 5 5 5 5
In your example iterator
is just an iterator one past the last element of the vector and brings no big advantage because it is the same as v.end()
.
Upvotes: 4
Reputation: 238401
It's an output iterator. You an use it like any output iterator. It is the same type that you pass as the first argument - even same value in case nothing is generated.
Back inserter isn't exactly ideal example for this because it doesn't really care about the position (fun fact: incrementing a back inserter does nothing). A more important use case is an iterator to an existing element in which case we care about which elements we are writing over.
An extended example, using two different generators for the same container:
auto generator1 = [&]() { return j++; };
auto generator2 = [&]() { return j--; };
auto it = v.begin();
it = std::generate_n(it, 5, generator1);
it = std::generate_n(it, 5, generator2);
Upvotes: 5