Figure 16.1 demonstrates algorithms fill
, fill_n
, generate
and generate_n
. Algorithms fill and fill_n set every element in a range of container elements to a specific value. Algorithms generate and generate_n use a generator function to create values for every element in a range of container elements. The generator function takes no arguments and returns a value that can be placed in an element of the container.
1 // Fig. 16.1: fig16_01.cpp
2 // Algorithms fill, fill_n, generate and generate_n.
3 #include <iostream>
4 #include <algorithm> // algorithm definitions
5 #include <array> // array class-template definition
6 #include <iterator> // ostream_iterator
7 using namespace std;
8
9 char nextLetter(); // prototype of generator function
10
11 int main()
12 {
13 array< char, 10 > chars;
14 ostream_iterator< char > output( cout, " " );
15 fill( chars.begin(), chars.end(), '5' ); // fill chars with 5s
16
17 cout << "chars after filling with 5s:
";
18 copy( chars.cbegin(), chars.cend(), output );
19
20 // fill first five elements of chars with As
21 fill_n( chars.begin(), 5, 'A' );
22
23 cout << "
chars after filling five elements with As:
";
24 copy( chars.cbegin(), chars.cend(), output );
25
26 // generate values for all elements of chars with nextLetter
27 generate( chars.begin(), chars.end(), nextLetter );
28
29 cout << "
chars after generating letters A-J:
";
30 copy( chars.cbegin(), chars.cend(), output );
31
32 // generate values for first five elements of chars with nextLetter
33 generate_n( chars.begin(), 5, nextLetter );
34
35 cout << "
chars after generating K-O for the"
36 << " first five elements:
";
37 copy( chars.cbegin(), chars.cend(), output );
38 cout << endl;
39 } // end main
40
41 // generator function returns next letter (starts with A)
42 char nextLetter()
43 {
44 static char letter = 'A';
45 return letter++;
46 } // end function nextLetter
chars after filling with 5s:
5 5 5 5 5 5 5 5 5 5
chars after filling five elements with As:
A A A A A 5 5 5 5 5
chars after generating letters A-J:
A B C D E F G H I J
chars after generating K-O for the first five elements:
K L M N O F G H I J
Line 13 defines a 10-element array
of char
values. Line 15 uses the fill
algorithm to place the character '5'
in every element of chars
from chars.begin()
up to, but not including, chars.end()
. The iterators supplied as the first and second argument must be at least forward iterators (i.e., they can be used for both input from a container and output to a container in the forward direction).
Line 21 uses the fill_n
algorithm to place the character 'A'
in the first five elements of chars
. The iterator supplied as the first argument must be at least an output iterator (i.e., it can be used to write into a container in the forward direction). The second argument specifies the number of elements to fill. The third argument specifies the value to place in each element.
Line 27 uses the generate
algorithm to place the result of a call to generator function nextLetter
in every element of chars
from chars.begin()
up to, but not including, chars.end()
. The iterators supplied as the first and second arguments must be at least forward iterators. Function nextLetter
(lines 42–46) begins with the character 'A'
maintained in a static
local variable. The statement in line 45 postincrements the value of letter
and returns the old value of letter
each time nextLetter
is called.
Line 33 uses the generate_n
algorithm to place the result of a call to generator function nextLetter
in five elements of chars
, starting from chars.begin()
. The iterator supplied as the first argument must be at least an output iterator.
When you look at the Standard Library algorithms documentation for algorithms that can receive function pointers as arguments, you’ll notice in the documentation that the corresponding parameters do not show pointer declarations. Such parameters can actually receive as arguments function pointers, function objects (Section 16.4) or lambda expressions (Section 16.5). For this reason, the Standard Library declares such parameters using more generic names.
For example, the generate
algorithm’s prototype is listed in the C++ standard document as:
template<class ForwardIterator, class Generator>
void generate(ForwardIterator first, ForwardIterator last,
Generator gen);
indicating that generate
expects as arguments ForwardIterators representing the range of elements to process and a Generator function. The standard explains that the algorithm calls the Generator
function to obtain a value for each element in the range specified by the ForwardIterators. The standard also specifies that the Generator
must take no arguments and return a value of the element type.
Similar documentation is provided for each algorithm that can receive a function pointer, function object or lambda expression. In most of this chapter’s examples, as we present each algorithm, we specify the requirements for such parameters. We typically do so in the context of functions, and pass function pointers into the algorithms. In Sections 16.4–16.5, we discuss how to create and use function objects and lambda expressions that you can pass to algorithms.