Skip to main content

std::ranges::generate_n() algorithm

// (1)
constexpr O generate_n( O first, std::iter_difference_t<O> n, F gen );

The type of arguments are generic and have following constraints:

  • O - std::input_or_output_iterator
  • F - std::copy_constructible

Additionally, each overload has the following constraints:

  • (1) - invocable<F&> && indirectly_writable<O, invoke_result_t<F&>>

(The std:: namespace was ommitted here for readability)

Assigns the result of successive invocations of the function object gen to each element in the range [first; first + n), if 0 < n.
Does nothing otherwise.

The function-like entities described on this page are niebloids.

Parameters

first

The beginning of the range of elements to modify.

n

Number of elements to modify.

gen

The generator function object.

Return value

Iterator one past the last element assigned if 0 < count, first otherwise.

Complexity

Exactly n invocations of gen() and assignments.

Exceptions

(none)

Possible implementation

generate_n(1)
struct generate_n_fn
{
template<std::input_or_output_iterator O, std::copy_constructible F>
requires std::invocable<F&> && std::indirectly_writable<O, std::invoke_result_t<F&>>
constexpr O operator()(O first, std::iter_difference_t<O> n, F gen) const
{
for (; n-- > 0; *first = std::invoke(gen), ++first)
{}
return first;
}
};

inline constexpr generate_n_fn generate_n {};

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
#include <string_view>

auto dice()
{
static std::uniform_int_distribution<int> distr {1, 6};
static std::random_device engine;
static std::mt19937 noise {engine()};
return distr(noise);
}

void print(const auto& v, std::string_view comment)
{
for (int i : v)
std::cout << i << ' ';
std::cout << '(' << comment << ")\n";
}

int main()
{
std::array<int, 8> v;

std::ranges::generate_n(v.begin(), v.size(), dice);
print(v, "dice");

std::ranges::generate_n(v.begin(), v.size(), [n {0}] mutable { return n++; });
// same effect as std::iota(v.begin(), v.end(), 0);
print(v, "iota");
}
Output
5 5 2 2 6 6 3 5 (dice)
0 1 2 3 4 5 6 7 (iota)
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::ranges::generate_n() algorithm

// (1)
constexpr O generate_n( O first, std::iter_difference_t<O> n, F gen );

The type of arguments are generic and have following constraints:

  • O - std::input_or_output_iterator
  • F - std::copy_constructible

Additionally, each overload has the following constraints:

  • (1) - invocable<F&> && indirectly_writable<O, invoke_result_t<F&>>

(The std:: namespace was ommitted here for readability)

Assigns the result of successive invocations of the function object gen to each element in the range [first; first + n), if 0 < n.
Does nothing otherwise.

The function-like entities described on this page are niebloids.

Parameters

first

The beginning of the range of elements to modify.

n

Number of elements to modify.

gen

The generator function object.

Return value

Iterator one past the last element assigned if 0 < count, first otherwise.

Complexity

Exactly n invocations of gen() and assignments.

Exceptions

(none)

Possible implementation

generate_n(1)
struct generate_n_fn
{
template<std::input_or_output_iterator O, std::copy_constructible F>
requires std::invocable<F&> && std::indirectly_writable<O, std::invoke_result_t<F&>>
constexpr O operator()(O first, std::iter_difference_t<O> n, F gen) const
{
for (; n-- > 0; *first = std::invoke(gen), ++first)
{}
return first;
}
};

inline constexpr generate_n_fn generate_n {};

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <random>
#include <string_view>

auto dice()
{
static std::uniform_int_distribution<int> distr {1, 6};
static std::random_device engine;
static std::mt19937 noise {engine()};
return distr(noise);
}

void print(const auto& v, std::string_view comment)
{
for (int i : v)
std::cout << i << ' ';
std::cout << '(' << comment << ")\n";
}

int main()
{
std::array<int, 8> v;

std::ranges::generate_n(v.begin(), v.size(), dice);
print(v, "dice");

std::ranges::generate_n(v.begin(), v.size(), [n {0}] mutable { return n++; });
// same effect as std::iota(v.begin(), v.end(), 0);
print(v, "iota");
}
Output
5 5 2 2 6 6 3 5 (dice)
0 1 2 3 4 5 6 7 (iota)
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.