std::ranges::generate

来自cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
算法库
受约束算法及范围上的算法 (C++20)
受约束算法: std::ranges::copy, std::ranges::sort, ...
执行策略 (C++17)
不修改序列的操作
(C++11)(C++11)(C++11)
(C++17)
修改序列的操作
Partitioning operations
划分操作
排序操作
(C++11)
二分搜索操作
集合操作(在已排序范围上)
堆操作
(C++11)
最小/最大操作
(C++11)
(C++17)

排列
数值运算
未初始化存储上的操作
(C++17)
(C++17)
(C++17)
C 库
 
受约束算法
不修改序列的操作
修改序列的操作
划分操作
排序操作
二分搜索操作
集合操作(在已排序范围上)
堆操作
最小/最大操作
排列
未初始化存储上的操作
返回类型
 
在标头 <algorithm> 定义
调用签名
template< std::input_or_output_iterator O, std::sentinel_for<O> S,

          std::copy_constructible F >
requires  std::invocable<F&> && std::indirectly_writable<O, std::invoke_result_t<F&>>
constexpr O

          generate( O first, S last, F gen );
(1) (C++20 起)
template< class R, std::copy_constructible F >

requires  std::invocable<F&> && ranges::output_range<R, std::invoke_result_t<F&>>
constexpr ranges::borrowed_iterator_t<R>

          generate( R&& r, F gen );
(2) (C++20 起)
1) 对范围 [first, last) 中的每个元素赋值连续调用函数对象 gen 的结果。
2)(1) ,但以 r 为范围,如同以 ranges::begin(r)first 并以 ranges::end(r)last

此页面上描述的仿函数实体是 niebloid,即:

实际上,它们能以函数对象,或者某些特殊编译器扩展实现。

参数

first, last - 要修改的元素范围
r - 要修改的元素范围
gen - 生成器函数对象

返回值

比较等于 last 的迭代器。

复杂度

准确调用 ranges::distance(first, last)gen() 以及赋值。

可能的实现

struct generate_fn {
  template<std::input_or_output_iterator O, std::sentinel_for<O> S,
           std::copy_constructible F>
    requires std::invocable<F&> && std::indirectly_writable<O, std::invoke_result_t<F&>>
      constexpr O operator()( O first, S last, F gen ) const {
        for (; first != last; *first = std::invoke(gen), ++first);
        return first;
      }
  template<class R, std::copy_constructible F>
    requires std::invocable<F&> && ranges::output_range<R, std::invoke_result_t<F&>>
      constexpr ranges::borrowed_iterator_t<R> operator()( R&& r, F gen ) const {
        return (*this)(ranges::begin(r), ranges::end(r), std::move(gen));
      }
};
 
inline constexpr generate_fn generate{};

示例

#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 device;
    static std::mt19937 engine{device()};
    return distr(engine);
}
 
void iota(auto& v, int n) {
    std::ranges::generate(v, [&n] () mutable { return n++; });
}
 
void print(std::string_view comment, const auto& v) {
    for (std::cout << comment; int i : v) { std::cout << i << ' '; }
    std::cout << '\n';
}
 
int main()
{
    std::array<int, 8> v;
 
    std::ranges::generate(v.begin(), v.end(), dice);
    print("dice: ", v);
    std::ranges::generate(v, dice);
    print("dice: ", v);
 
    iota(v, 1);
    print("iota: ", v);
}

可能的输出:

dice: 4 3 1 6 6 4 5 5 
dice: 4 2 5 3 6 2 6 2 
iota: 1 2 3 4 5 6 7 8

参阅

保存 N 次函数应用的结果
(niebloid)
将一个给定值复制赋值给一个范围内的每个元素
(niebloid)
将一个值复制赋值给一定量的元素
(niebloid)
将一个函数应用于某一范围的各个元素
(niebloid)
将相继的函数调用结果赋值给一个范围中的每个元素
(函数模板)