Assigning algorithms in the C++ Standard Library

The C++ Standard Library provides several algorithms for assigning values to a range (such as a container or a C-array).

fill and fill_n

std::fill assigns a given value to all the elements in a range. It is available in the header <algorithm>. In the following example all elements of a vector of integers are assigned the value 1.

std::vector data(10);
std::fill(std::begin(data), std::end(data), 1);

std::fill_n is similar, but instead taking the bounds of a range it takes the beginning and a count and initializes N elements starting from the specified first element. You must make sure that first + count does not exceed the bounds of the range. The following example is an equivalent of the first:

std::vector data(10);
std::fill_n(std::begin(data), data.size(), 1);

generate and generate_n

These algorithms are similar to the first, but instead of taking a value to assign they take a function and assign the value returned by the function. They are also available in the header <algorithm>.

std::generate assigns the elements in a range the values returned by a function.

In the following example we initialize a vector of 10 elements with random numbers (using a Marsenne twister engine).

std::mt19937 rnd(static_cast<unsigned int>(std::chrono::system_clock::now().time_since_epoch().count()));
std::vector<int> data(10);
std::generate(std::begin(data), std::end(data), rnd);

for(auto const & d : data)
{
   std::cout << d << std::endl;
}

The result may look like this:

-630855823
-1828303634
473207879
1464137724
1046536659
1518951902
1516051318
-2076855687
-1620034611
-991968006

You can use lambdas as the function whose return value is stored into the range. The following example generates random numbers ranging from 1 to 100 with a uniform distribution.

std::mt19937 rnd(static_cast(std::chrono::system_clock::now().time_since_epoch().count()));
std::vector data(10);
std::uniform_int_distribution<> ud(1, 100);
std::generate(std::begin(data), std::end(data), [&](){return ud(rnd);});

for(auto const & d : data)
{
   std::cout << d << std::endl;
}

Result may look like this:

48
10
15
63
34
2
22
71
15
37

std::generate_n is similar, but instead of taking the limits of the range it takes the beginning and a count and assigns the first N values returned by the function to the range. You must makes sure that first + count does not exceeds the bounds of the range.

In the following example we initialize the elements of a vector with values from 1 to N, where N is the size of the range.

std::vector data(10);
int n = 1;
std::generate_n(std::begin(data), data.size(), [&](){return n++;});

for(auto const & d : data)
{
   std::cout << d << std::endl;
}

The result is:

1
2
3
4
5
6
7
8
9
10

iota

std::iota is a new algorithm to C++11. It assigns the elements of a range with sequentially increasing values starting from a given value. The algorithm is available in header <numeric>.

The following example initializes the elements of a vector with values from 1 to N, where N is the size of the range (basically the same thing we did in the last example).

std::vector data(10);
std::iota(std::begin(data), std::end(data), 1);

for(auto const & d : data)
{
   std::cout << d << std::endl;
}

The result is:

1
2
3
4
5
6
7
8
9
10

Notice that the term iota is taken from the APL programming language and denotes the Greek letter used in various mathematical notations.

3 thoughts on “Assigning algorithms in the C++ Standard Library”

Leave a Comment