Szablony generate
i generate_n
pozwalają przypisać wartości zwracane przez generator do elementów tablicy lub kontenera udostępniającego iterator. Są szczególnie przydatne wtedy, gdy kontener chcemy wypełnić zgodnie z jakąś zależnością funkcyjną. Można z nich również korzystać w celu przypisania kolejnym elementom losowych wartości.
Generatorem może być bezargumentowa funkcja lub obiekt funkcyjny1), zwracający obiekty takiego samego typu, jak przechowywane w kontenerze.
#include <algorithm> // tu jest definicja szablonów generate i generate_n template <class ForwardIterator, class Generator> void generate ( ForwardIterator first, ForwardIterator last, Generator gen )
generate
przypisuje wartość zwracaną przez kolejne wywołania gen
począwszy od elementu first
(włącznie z first
) skończywszy na last
(bez last
). Pozwala więc w intuicyjny sposób przypisać wartości elementom należącym do kontenera.
first
- iterator pierwszego elementu konteneralast
- iterator elementu za ostatnim w kontenerzegen
- bezargumentowa funkcja lub funktor zwracająca obiekty typu przechowywanego przez kontener; wartość zwracana przez jej kolejne wywołania jest przypisywana kolejnym elementom./* Wypełnia wektor "losowymi" wartościami */ int random() { return 4; } //patrz http://www.metasploit.com/users/hdm/tools/debian-openssl/ const size_t size = 3; vector<int> v = vector<int>(size); generate(v.begin(), v.end(), random);
#include <algorithm> // tu jest definicja szablonów generate i generate_n template <class OutputIterator, class Size, class Generator> void generate_n ( OutputIterator first, Size n, Generator gen )
generate_n
przypisuje wartość zwracaną przez kolejne wywołania gen
począwszy od elementu first
(włącznie z first
) dla n
kolejnych elementów.
first
- iterator pierwszego elementu konteneran
- ilość kolejnych elementów do przypisaniagen
- bezargumentowa funkcja lub funktor zwracająca obiekty typu przechowywanego przez kontener; wartość zwracana przez jej kolejne wywołania jest przypisywana kolejnym elementom./* Wypisuje "losowe" wartości na stdout */ int random() { return 9; } const size_t size = 3; generate_n(ostream_iterator<int>(cout, " "), size, random);
Wydawać by się mogło, że szablony generate
i generate_n
w gruncie rzeczy robią to samo, więc są redundantne. Przecież wywołanie:
generate_n (first, n, gen)
można zastąpić przez:
generate (first, first+n, gen)
Jednak w funkcjach tych występują inne wymagania co do iteratora. Do wywołania generate
potrzebny jest iterator wskazujący na koniec kontenera. A może się zdarzyć, że:
Przykładowo takiej operacji (patrz generate2.cpp):
generate_n(ostream_iterator<GeneticAlgorithm::Individual>(os, " "), 10, ga.rig_)
za pomocą generate
wykonać się nie da.
Długi przykład zastosowania algorytmu dotyczy pewnego szkieletu algorytmu genetycznego, a dokładniej generacji populacji początkowej.
Kolorowy kod programu znajduje się tutaj. To samo w postaci pliku źródłowego: generate2.cpp
Szablony generate
i generate_n
umożliwiają łatwe wypełnianie kolekcji wartościami zwracanymi przez funkcje lub funktory. Są przydatne tam, gdzie wartości początkowe elementów kontenera zależą od stanu generatora.
operator()