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.