Skip to content

Commit d376613

Browse files
committed
random : C++26対応として、generate_random関数を追加 (close #1339)
1 parent 0eca2a4 commit d376613

File tree

3 files changed

+164
-1
lines changed

3 files changed

+164
-1
lines changed

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
288288
- [`std::real()`](/reference/complex/complex/real_free.md) (算術型オーバーロード)
289289
- [`std::complex`](/reference/complex/complex.md)を構造化束縛や、将来のパターンマッチで使用できるようタプルインタフェースの特殊化を追加
290290
- [`<random>`](/reference/random.md)の範囲`[0, 1)`の乱数を生成する[`std::generate_canonical()`](/reference/random/generate_canonical.md)を、望ましい統計的性質を保証するようアルゴリズムと制約を変更
291-
- [`<random>`](/reference/random.md)に、乱数列を生成する[`std::ranges::generate_random()`](/reference/random/generate_random.md.nolink)関数を追加
291+
- [`<random>`](/reference/random.md)に、乱数列を生成する[`std::ranges::generate_random()`](/reference/random/generate_random.md)関数を追加
292292

293293

294294
### ユーティリティ

reference/random.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@
143143
| 名前 | 説明 | 対応バージョン |
144144
|----------------|------------------------------|-------|
145145
| [`generate_canonical`](random/generate_canonical.md) | 実数区間\[0.0,1.0\)に展開(事実上正規化)された一様分布乱数を得る(function template) | C++11 |
146+
| [`generate_random`](random/generate_random.md) | 乱数列を生成する(function template) | C++26 |
146147

147148

148149
##
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# generate_random
2+
* random[meta header]
3+
* std[meta namespace]
4+
* function template[meta id-type]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::ranges {
9+
template <class R, class G>
10+
requires output_range<R, invoke_result_t<G&>> &&
11+
uniform_random_bit_generator<remove_cvref_t<G>>
12+
constexpr borrowed_iterator_t<R>
13+
generate_random(R&& r, G&& g); // (1) C++26
14+
15+
template <class G,
16+
output_iterator<invoke_result_t<G&>> O,
17+
sentinel_for<O> S>
18+
requires uniform_random_bit_generator<remove_cvref_t<G>>
19+
constexpr O
20+
generate_random(O first, S last, G&& g); // (2) C++26
21+
22+
template <class R, class G, class D>
23+
requires output_range<R, invoke_result_t<D&, G&>> &&
24+
invocable<D&, G&> &&
25+
uniform_random_bit_generator<remove_cvref_t<G>>
26+
constexpr borrowed_iterator_t<R>
27+
generate_random(R&& r, G&& g, D&& d); // (3) C++26
28+
29+
template <class G,
30+
class D,
31+
output_iterator<invoke_result_t<D&, G&>> O,
32+
sentinel_for<O> S>
33+
requires invocable<D&, G&> &&
34+
uniform_random_bit_generator<remove_cvref_t<G>>
35+
constexpr O
36+
generate_random(O first, S last, G&& g, D&& d); // (4) C++26
37+
}
38+
```
39+
* output_range[link /reference/ranges/output_range.md]
40+
* uniform_random_bit_generator[link uniform_random_bit_generator.md]
41+
* invoke_result_t[link /reference/type_traits/invoke_result.md]
42+
* remove_cvref_t[link /reference/type_traits/remove_cvref.md]
43+
* borrowed_iterator_t[link /reference/ranges/borrowed_iterator_t.md]
44+
* output_iterator[link /reference/iterator/output_iterator.md]
45+
* sentinel_for[link /reference/iterator/sentinel_for.md]
46+
* invocable[link /reference/concepts/invocable.md]
47+
48+
## 概要
49+
乱数列を生成する。
50+
51+
- (1) : 出力範囲`r`の各要素に、乱数生成器`g`で生成した乱数を代入する
52+
- (2) : 出力イテレータ範囲`[first, last)`の各要素に、乱数生成器`g`で生成した乱数を代入する
53+
- (3) : 出力範囲`r`の各要素に、乱数生成器`g`と分布生成器`d`で生成した乱数を代入する
54+
- (4) : 出力イテレータ範囲`[first, last)`の各要素に、乱数生成器`g`と分布生成器`d`で生成した乱数を代入する
55+
56+
この関数は、`for`文を使用した以下のコードをアルゴリズム関数化したものである。
57+
58+
```cpp
59+
std::vector<int> v(10);
60+
std::mt19937 gen {std::random_device{}()};
61+
std::uniform_int_distribution<int> dist{1, 100};
62+
63+
// 以下の3つのコードは等価
64+
std::ranges::generate_random(v, gen); // (1)
65+
std::ranges::generate_random(v.begin(), v.end(), gen); // (2)
66+
for (auto& x : v) {
67+
x = gen();
68+
}
69+
70+
// 以下の3つのコードは等価
71+
std::ranges::generate_random(v, gen, dist); // (3)
72+
std::ranges::generate_random(v.begin(), v.end(), gen, dist); // (4)
73+
for (auto& x : v) {
74+
x = dist(gen);
75+
}
76+
```
77+
78+
79+
## 効果
80+
- (1) :
81+
- `g.generate_random(`[`std::forward`](/reference/utility/forward.md)`<R>(r))`が妥当な式であれば、それを呼び出す
82+
- 備考 : 乱数生成器が`generate_random()`メンバ関数をもっていればそれを使用する
83+
- そうでなく、`R`[`sized_range`](/reference/ranges/sized_range.md)のモデルである場合、値`N`[`span`](/reference/span/span.md)`<`[`invoke_result_t`](/reference/type_traits/invoke_result.md)`<G&>, N>`型オブジェクト`s`に対して、式`g()`または`g.generate_random(s)`を未規定の回数だけ呼び出して実行し、`r`の各要素に代入する
84+
- 備考 : ここでの`N`は乱数生成の回数と異なってもよい
85+
- そうでなければ、[`ranges::generate`](/reference/algorithm/ranges_generate.md)`(`[`std::forward`](/reference/utility/forward.md)`<R>(r), ref(g))`を呼び出す
86+
- 備考 : [`std::forward_list`](/reference/forward_list/forward_list.md)のような`size()`メンバ関数をもたないコンテナがこちらに該当する
87+
88+
- (2) : 以下と等価
89+
```cpp
90+
return generate_random(subrange<O, S>(std::move(first), last), g);
91+
```
92+
* subrange[link /reference/ranges/subrange.md]
93+
* std::move[link /reference/utility/move.md]
94+
95+
- (3) :
96+
- `d.generate_random(`[`std::forward`](/reference/utility/forward.md)`<R>(r), g)`が妥当な式であれば、それを呼び出す
97+
- 備考 : 分布生成器が`generate_random()`メンバ関数をもっていればそれを使用する
98+
- そうでなく、`R`が[`sized_range`](/reference/ranges/sized_range.md)のモデルである場合、値`N`と[`span`](/reference/span/span.md)`<`[`invoke_result_t`](/reference/type_traits/invoke_result.md)`<D&, G&>, N>`型オブジェクト`s`に対して、式[`invoke`](/reference/functional/invoke.md)`(d, g)`または`d.generate_random(s, g)`を未規定の回数だけ呼び出して実行し、`r`の各要素に代入する
99+
- 備考 : ここでの`N`は乱数生成の回数と異なってもよい
100+
- そうでなければ、[`ranges::generate`](/reference/algorithm/ranges_generate.md)`(`[`std::forward`](/reference/utility/forward.md)`<R>(r), [&d, &g] { return` [`invoke`](/reference/functional/invoke.md)`(d, g); })`を呼び出す
101+
- 備考 : [`std::forward_list`](/reference/forward_list/forward_list.md)のような`size()`メンバ関数をもたないコンテナがこちらに該当する
102+
103+
- (4) : 以下と等価
104+
```cpp
105+
return generate_random(subrange<O, S>(std::move(first), last), g, d);
106+
```
107+
* subrange[link /reference/ranges/subrange.md]
108+
* std::move[link /reference/utility/move.md]
109+
110+
111+
## 戻り値
112+
- (1), (3) :
113+
```cpp
114+
return ranges::end(r);
115+
```
116+
* ranges::end[link /reference/ranges/end.md]
117+
118+
119+
## 例
120+
```cpp example
121+
#include <random>
122+
#include <print>
123+
#include <vector>
124+
125+
int main()
126+
{
127+
std::random_device seed_gen;
128+
std::mt19937 engine(seed_gen());
129+
std::uniform_int_distribution<int> dist{0, 100};
130+
131+
std::vector<int> v(10);
132+
133+
// コンテナの全要素を乱数で埋める
134+
std::ranges::generate_random(v, engine);
135+
std::println("{}", v);
136+
137+
// コンテナの全要素を、指定した分布の乱数で埋める
138+
std::ranges::generate_random(v, engine, dist);
139+
std::println("{}", v);
140+
}
141+
```
142+
* std::generate_canonical[color ff0000]
143+
* digits[link /reference/limits/numeric_limits/digits.md]
144+
145+
### 出力
146+
```
147+
[2034091041, 1919373608, 514210727, -1154669807, -315048337, -1224623446, -1986406128, -1034429876, -844125616, 1858136340]
148+
[83, 25, 48, 15, 9, 60, 47, 31, 91, 54]
149+
```
150+
151+
## バージョン
152+
### 言語
153+
- C++26
154+
155+
### 処理系
156+
- [Clang](/implementation.md#clang): 19.0 [mark noimpl]
157+
- [GCC](/implementation.md#gcc): 14 [mark noimpl]
158+
- [Visual C++](/implementation.md#visual_cpp): 2022 Update 10 [mark noimpl]
159+
160+
161+
## 参照
162+
- [P1068R11 Vector API for random number generation](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p1068r11.pdf)

0 commit comments

Comments
 (0)