namespace std::ranges {
template <class R, class G>
requires output_range<R, invoke_result_t<G&>> &&
uniform_random_bit_generator<remove_cvref_t<G>>
constexpr borrowed_iterator_t<R>
generate_random(R&& r, G&& g); // (1) C++26
template <class G,
output_iterator<invoke_result_t<G&>> O,
sentinel_for<O> S>
requires uniform_random_bit_generator<remove_cvref_t<G>>
constexpr O
generate_random(O first, S last, G&& g); // (2) C++26
template <class R, class G, class D>
requires output_range<R, invoke_result_t<D&, G&>> &&
invocable<D&, G&> &&
uniform_random_bit_generator<remove_cvref_t<G>>
constexpr borrowed_iterator_t<R>
generate_random(R&& r, G&& g, D&& d); // (3) C++26
template <class G,
class D,
output_iterator<invoke_result_t<D&, G&>> O,
sentinel_for<O> S>
requires invocable<D&, G&> &&
uniform_random_bit_generator<remove_cvref_t<G>>
constexpr O
generate_random(O first, S last, G&& g, D&& d); // (4) C++26
}
概要
乱数列を生成する。
- (1) : 出力範囲
r
の各要素に、乱数生成器g
で生成した乱数を代入する - (2) : 出力イテレータ範囲
[first, last)
の各要素に、乱数生成器g
で生成した乱数を代入する - (3) : 出力範囲
r
の各要素に、乱数生成器g
と分布生成器d
で生成した乱数を代入する - (4) : 出力イテレータ範囲
[first, last)
の各要素に、乱数生成器g
と分布生成器d
で生成した乱数を代入する
この関数は、for
文を使用した以下のコードをアルゴリズム関数化したものである。
std::vector<int> v(10);
std::mt19937 gen {std::random_device{}()};
std::uniform_int_distribution<int> dist{1, 100};
// 以下の3つのコードは等価
std::ranges::generate_random(v, gen); // (1)
std::ranges::generate_random(v.begin(), v.end(), gen); // (2)
for (auto& x : v) {
x = gen();
}
// 以下の3つのコードは等価
std::ranges::generate_random(v, gen, dist); // (3)
std::ranges::generate_random(v.begin(), v.end(), gen, dist); // (4)
for (auto& x : v) {
x = dist(gen);
}
効果
-
(1) :
g.generate_random(std::forward<R>(r))
が妥当な式であれば、それを呼び出す- 備考 : 乱数生成器が
generate_random()
メンバ関数をもっていればそれを使用する
- 備考 : 乱数生成器が
- そうでなく、
R
がsized_range
のモデルである場合、値N
とspan<invoke_result_t<G&>, N>
型オブジェクトs
に対して、式g()
またはg.generate_random(s)
を未規定の回数だけ呼び出して実行し、r
の各要素に代入する- 備考 : ここでの
N
は乱数生成の回数と異なってもよい
- 備考 : ここでの
- そうでなければ、
ranges::generate(std::forward<R>(r), ref(g))
を呼び出す- 備考 :
std::forward_list
のようなsize()
メンバ関数をもたないコンテナがこちらに該当する
- 備考 :
-
(2) : 以下と等価
-
(3) :
d.generate_random(std::forward<R>(r), g)
が妥当な式であれば、それを呼び出す- 備考 : 分布生成器が
generate_random()
メンバ関数をもっていればそれを使用する
- 備考 : 分布生成器が
- そうでなく、
R
がsized_range
のモデルである場合、値N
とspan<invoke_result_t<D&, G&>, N>
型オブジェクトs
に対して、式invoke(d, g)
またはd.generate_random(s, g)
を未規定の回数だけ呼び出して実行し、r
の各要素に代入する- 備考 : ここでの
N
は乱数生成の回数と異なってもよい
- 備考 : ここでの
- そうでなければ、
ranges::generate(std::forward<R>(r), [&d, &g] { return invoke(d, g); })
を呼び出す- 備考 :
std::forward_list
のようなsize()
メンバ関数をもたないコンテナがこちらに該当する
- 備考 :
-
(4) : 以下と等価
戻り値
- (1), (3) :
return ranges::end(r);
例
#include <random>
#include <print>
#include <vector>
int main()
{
std::random_device seed_gen;
std::mt19937 engine(seed_gen());
std::uniform_int_distribution<int> dist{0, 100};
std::vector<int> v(10);
// コンテナの全要素を乱数で埋める
std::ranges::generate_random(v, engine);
std::println("{}", v);
// コンテナの全要素を、指定した分布の乱数で埋める
std::ranges::generate_random(v, engine, dist);
std::println("{}", v);
}
21
#include <random>
#include <print>
#include <vector>
int main()
{
std::random_device seed_gen;
std::mt19937 engine(seed_gen());
std::uniform_int_distribution<int> dist{0, 100};
std::vector<int> v(10);
// コンテナの全要素を乱数で埋める
std::ranges::generate_random(v, engine);
std::println("{}", v);
// コンテナの全要素を、指定した分布の乱数で埋める
std::ranges::generate_random(v, engine, dist);
出力例
[2034091041, 1919373608, 514210727, -1154669807, -315048337, -1224623446, -1986406128, -1034429876, -844125616, 1858136340]
[83, 25, 48, 15, 9, 60, 47, 31, 91, 54]
バージョン
言語
- C++26
処理系
- Clang: 19.0 ❌
- GCC: 14 ❌
- Visual C++: 2022 Update 10 ❌