1*732cb123SKonstantin Varlamov //===----------------------------------------------------------------------===//
2*732cb123SKonstantin Varlamov //
3*732cb123SKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*732cb123SKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
5*732cb123SKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*732cb123SKonstantin Varlamov //
7*732cb123SKonstantin Varlamov //===----------------------------------------------------------------------===//
8*732cb123SKonstantin Varlamov
9*732cb123SKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
10*732cb123SKonstantin Varlamov // UNSUPPORTED: libcpp-has-no-incomplete-ranges
11*732cb123SKonstantin Varlamov
12*732cb123SKonstantin Varlamov // <algorithm>
13*732cb123SKonstantin Varlamov
14*732cb123SKonstantin Varlamov // template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Gen>
15*732cb123SKonstantin Varlamov // requires (forward_iterator<I> || random_access_iterator<O>) &&
16*732cb123SKonstantin Varlamov // indirectly_copyable<I, O> &&
17*732cb123SKonstantin Varlamov // uniform_random_bit_generator<remove_reference_t<Gen>>
18*732cb123SKonstantin Varlamov // O sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g); // Since C++20
19*732cb123SKonstantin Varlamov //
20*732cb123SKonstantin Varlamov // template<input_range R, weakly_incrementable O, class Gen>
21*732cb123SKonstantin Varlamov // requires (forward_range<R> || random_access_iterator<O>) &&
22*732cb123SKonstantin Varlamov // indirectly_copyable<iterator_t<R>, O> &&
23*732cb123SKonstantin Varlamov // uniform_random_bit_generator<remove_reference_t<Gen>>
24*732cb123SKonstantin Varlamov // O sample(R&& r, O out, range_difference_t<R> n, Gen&& g); // Since C++20
25*732cb123SKonstantin Varlamov
26*732cb123SKonstantin Varlamov #include <algorithm>
27*732cb123SKonstantin Varlamov #include <array>
28*732cb123SKonstantin Varlamov #include <concepts>
29*732cb123SKonstantin Varlamov #include <functional>
30*732cb123SKonstantin Varlamov #include <random>
31*732cb123SKonstantin Varlamov #include <ranges>
32*732cb123SKonstantin Varlamov #include <utility>
33*732cb123SKonstantin Varlamov
34*732cb123SKonstantin Varlamov #include "almost_satisfies_types.h"
35*732cb123SKonstantin Varlamov #include "test_iterators.h"
36*732cb123SKonstantin Varlamov #include "test_macros.h"
37*732cb123SKonstantin Varlamov
38*732cb123SKonstantin Varlamov class RandGen {
39*732cb123SKonstantin Varlamov public:
min()40*732cb123SKonstantin Varlamov constexpr static size_t min() { return 0; }
max()41*732cb123SKonstantin Varlamov constexpr static size_t max() { return 255; }
42*732cb123SKonstantin Varlamov
operator ()()43*732cb123SKonstantin Varlamov constexpr size_t operator()() {
44*732cb123SKonstantin Varlamov flip = !flip;
45*732cb123SKonstantin Varlamov return flip;
46*732cb123SKonstantin Varlamov }
47*732cb123SKonstantin Varlamov
48*732cb123SKonstantin Varlamov private:
49*732cb123SKonstantin Varlamov bool flip = false;
50*732cb123SKonstantin Varlamov };
51*732cb123SKonstantin Varlamov
52*732cb123SKonstantin Varlamov static_assert(std::uniform_random_bit_generator<RandGen>);
53*732cb123SKonstantin Varlamov // `std::uniform_random_bit_generator` is a subset of requirements of `__libcpp_random_is_valid_urng`. Make sure that
54*732cb123SKonstantin Varlamov // a type satisfying the required minimum is still accepted by `ranges::shuffle`.
55*732cb123SKonstantin Varlamov LIBCPP_STATIC_ASSERT(!std::__libcpp_random_is_valid_urng<RandGen>::value);
56*732cb123SKonstantin Varlamov
57*732cb123SKonstantin Varlamov struct BadGen {
minBadGen58*732cb123SKonstantin Varlamov constexpr static size_t min() { return 255; }
maxBadGen59*732cb123SKonstantin Varlamov constexpr static size_t max() { return 0; }
60*732cb123SKonstantin Varlamov constexpr size_t operator()() const;
61*732cb123SKonstantin Varlamov };
62*732cb123SKonstantin Varlamov static_assert(!std::uniform_random_bit_generator<BadGen>);
63*732cb123SKonstantin Varlamov
64*732cb123SKonstantin Varlamov // Test constraints of the (iterator, sentinel) overload.
65*732cb123SKonstantin Varlamov // ======================================================
66*732cb123SKonstantin Varlamov
67*732cb123SKonstantin Varlamov template <class Iter = int*, class Sent = int*, class Out = int*, class Gen = RandGen>
68*732cb123SKonstantin Varlamov concept HasSampleIter =
69*732cb123SKonstantin Varlamov requires(Iter&& iter, Sent&& sent, Out&& out, std::iter_difference_t<Iter> n, Gen&& gen) {
70*732cb123SKonstantin Varlamov std::ranges::sample(std::forward<Iter>(iter), std::forward<Sent>(sent),
71*732cb123SKonstantin Varlamov std::forward<Out>(out), n, std::forward<Gen>(gen));
72*732cb123SKonstantin Varlamov };
73*732cb123SKonstantin Varlamov
74*732cb123SKonstantin Varlamov static_assert(HasSampleIter<int*, int*, int*, RandGen>);
75*732cb123SKonstantin Varlamov
76*732cb123SKonstantin Varlamov // !input_iterator<I>
77*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<InputIteratorNotDerivedFrom>);
78*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<InputIteratorNotIndirectlyReadable>);
79*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<InputIteratorNotInputOrOutputIterator>);
80*732cb123SKonstantin Varlamov
81*732cb123SKonstantin Varlamov // !sentinel_for<S, I>
82*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<int*, SentinelForNotSemiregular>);
83*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<int*, SentinelForNotWeaklyEqualityComparableWith>);
84*732cb123SKonstantin Varlamov
85*732cb123SKonstantin Varlamov // !weakly_incrementable<O>
86*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<int*, int*, WeaklyIncrementableNotMovable>);
87*732cb123SKonstantin Varlamov
88*732cb123SKonstantin Varlamov // (forward_iterator<I> || random_access_iterator<O>)
89*732cb123SKonstantin Varlamov static_assert(HasSampleIter<
90*732cb123SKonstantin Varlamov forward_iterator<int*>, forward_iterator<int*>,
91*732cb123SKonstantin Varlamov cpp20_output_iterator<int*>
92*732cb123SKonstantin Varlamov >);
93*732cb123SKonstantin Varlamov static_assert(HasSampleIter<
94*732cb123SKonstantin Varlamov cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>,
95*732cb123SKonstantin Varlamov random_access_iterator<int*>
96*732cb123SKonstantin Varlamov >);
97*732cb123SKonstantin Varlamov // !(forward_iterator<I> || random_access_iterator<O>)
98*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<
99*732cb123SKonstantin Varlamov cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>,
100*732cb123SKonstantin Varlamov cpp20_output_iterator<int*>
101*732cb123SKonstantin Varlamov >);
102*732cb123SKonstantin Varlamov
103*732cb123SKonstantin Varlamov // !indirectly_copyable<I, O>
104*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<int*, int*, int**>);
105*732cb123SKonstantin Varlamov
106*732cb123SKonstantin Varlamov // !uniform_random_bit_generator<remove_reference_t<Gen>>
107*732cb123SKonstantin Varlamov static_assert(!HasSampleIter<int*, int*, int*, BadGen>);
108*732cb123SKonstantin Varlamov
109*732cb123SKonstantin Varlamov // Test constraints of the (range) overload.
110*732cb123SKonstantin Varlamov // =========================================
111*732cb123SKonstantin Varlamov
112*732cb123SKonstantin Varlamov template <class Range, class Out = int*, class Gen = RandGen>
113*732cb123SKonstantin Varlamov concept HasSampleRange =
114*732cb123SKonstantin Varlamov requires(Range&& range, Out&& out, std::ranges::range_difference_t<Range> n, Gen&& gen) {
115*732cb123SKonstantin Varlamov std::ranges::sample(std::forward<Range>(range), std::forward<Out>(out), n, std::forward<Gen>(gen));
116*732cb123SKonstantin Varlamov };
117*732cb123SKonstantin Varlamov
118*732cb123SKonstantin Varlamov template <class T>
119*732cb123SKonstantin Varlamov using R = UncheckedRange<T>;
120*732cb123SKonstantin Varlamov
121*732cb123SKonstantin Varlamov static_assert(HasSampleRange<R<int*>, int*, RandGen>);
122*732cb123SKonstantin Varlamov
123*732cb123SKonstantin Varlamov // !input_range<R>
124*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<InputRangeNotDerivedFrom>);
125*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<InputRangeNotIndirectlyReadable>);
126*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<InputRangeNotInputOrOutputIterator>);
127*732cb123SKonstantin Varlamov
128*732cb123SKonstantin Varlamov // !weakly_incrementable<O>
129*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<R<int*>, WeaklyIncrementableNotMovable>);
130*732cb123SKonstantin Varlamov
131*732cb123SKonstantin Varlamov // (forward_range<R> || random_access_iterator<O>)
132*732cb123SKonstantin Varlamov static_assert(HasSampleRange<
133*732cb123SKonstantin Varlamov R<forward_iterator<int*>>,
134*732cb123SKonstantin Varlamov cpp20_output_iterator<int*>
135*732cb123SKonstantin Varlamov >);
136*732cb123SKonstantin Varlamov static_assert(HasSampleRange<
137*732cb123SKonstantin Varlamov R<cpp20_input_iterator<int*>>,
138*732cb123SKonstantin Varlamov random_access_iterator<int*>
139*732cb123SKonstantin Varlamov >);
140*732cb123SKonstantin Varlamov // !(forward_range<R> || random_access_iterator<O>)
141*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<
142*732cb123SKonstantin Varlamov R<cpp20_input_iterator<int*>>,
143*732cb123SKonstantin Varlamov cpp20_output_iterator<int*>
144*732cb123SKonstantin Varlamov >);
145*732cb123SKonstantin Varlamov
146*732cb123SKonstantin Varlamov // !indirectly_copyable<I, O>
147*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<R<int*>, int**>);
148*732cb123SKonstantin Varlamov
149*732cb123SKonstantin Varlamov // !uniform_random_bit_generator<remove_reference_t<Gen>>
150*732cb123SKonstantin Varlamov static_assert(!HasSampleRange<R<int*>, int*, BadGen>);
151*732cb123SKonstantin Varlamov
152*732cb123SKonstantin Varlamov template <class Iter, class Sent, class Out, size_t N, class Gen>
test_one(std::array<int,N> in,size_t n,Gen gen)153*732cb123SKonstantin Varlamov void test_one(std::array<int, N> in, size_t n, Gen gen) {
154*732cb123SKonstantin Varlamov assert(n <= static_cast<size_t>(N));
155*732cb123SKonstantin Varlamov
156*732cb123SKonstantin Varlamov auto verify_is_subsequence = [&] (auto output) {
157*732cb123SKonstantin Varlamov auto sorted_input = in;
158*732cb123SKonstantin Varlamov std::ranges::sort(sorted_input);
159*732cb123SKonstantin Varlamov auto sorted_output = std::ranges::subrange(output.begin(), output.begin() + n);
160*732cb123SKonstantin Varlamov std::ranges::sort(sorted_output);
161*732cb123SKonstantin Varlamov assert(std::ranges::includes(sorted_input, sorted_output));
162*732cb123SKonstantin Varlamov };
163*732cb123SKonstantin Varlamov
164*732cb123SKonstantin Varlamov { // (iterator, sentinel) overload.
165*732cb123SKonstantin Varlamov auto begin = Iter(in.data());
166*732cb123SKonstantin Varlamov auto end = Sent(Iter(in.data() + in.size()));
167*732cb123SKonstantin Varlamov std::array<int, N> output;
168*732cb123SKonstantin Varlamov auto out = Out(output.begin());
169*732cb123SKonstantin Varlamov
170*732cb123SKonstantin Varlamov std::same_as<Out> decltype(auto) result = std::ranges::sample(
171*732cb123SKonstantin Varlamov std::move(begin), std::move(end), std::move(out), n, gen);
172*732cb123SKonstantin Varlamov assert(base(result) == output.data() + n);
173*732cb123SKonstantin Varlamov verify_is_subsequence(output);
174*732cb123SKonstantin Varlamov // The output of `sample` is implementation-specific.
175*732cb123SKonstantin Varlamov }
176*732cb123SKonstantin Varlamov
177*732cb123SKonstantin Varlamov { // (range) overload.
178*732cb123SKonstantin Varlamov auto begin = Iter(in.data());
179*732cb123SKonstantin Varlamov auto end = Sent(Iter(in.data() + in.size()));
180*732cb123SKonstantin Varlamov std::array<int, N> output;
181*732cb123SKonstantin Varlamov auto out = Out(output.begin());
182*732cb123SKonstantin Varlamov
183*732cb123SKonstantin Varlamov std::same_as<Out> decltype(auto) result = std::ranges::sample(std::ranges::subrange(
184*732cb123SKonstantin Varlamov std::move(begin), std::move(end)), std::move(out), n, gen);
185*732cb123SKonstantin Varlamov assert(base(result) == output.data() + n);
186*732cb123SKonstantin Varlamov verify_is_subsequence(output);
187*732cb123SKonstantin Varlamov // The output of `sample` is implementation-specific.
188*732cb123SKonstantin Varlamov }
189*732cb123SKonstantin Varlamov }
190*732cb123SKonstantin Varlamov
191*732cb123SKonstantin Varlamov template <class Iter, class Sent, class Out>
test_iterators_iter_sent_out()192*732cb123SKonstantin Varlamov void test_iterators_iter_sent_out() {
193*732cb123SKonstantin Varlamov RandGen gen;
194*732cb123SKonstantin Varlamov
195*732cb123SKonstantin Varlamov // Empty sequence.
196*732cb123SKonstantin Varlamov test_one<Iter, Sent, Out, 0>({}, 0, gen);
197*732cb123SKonstantin Varlamov // 1-element sequence.
198*732cb123SKonstantin Varlamov test_one<Iter, Sent, Out, 1>({1}, 1, gen);
199*732cb123SKonstantin Varlamov // 2-element sequence.
200*732cb123SKonstantin Varlamov test_one<Iter, Sent, Out, 2>({1, 2}, 1, gen);
201*732cb123SKonstantin Varlamov test_one<Iter, Sent, Out, 2>({1, 2}, 2, gen);
202*732cb123SKonstantin Varlamov // n == 0.
203*732cb123SKonstantin Varlamov test_one<Iter, Sent, Out, 3>({1, 2, 3}, 0, gen);
204*732cb123SKonstantin Varlamov
205*732cb123SKonstantin Varlamov // Longer sequence.
206*732cb123SKonstantin Varlamov {
207*732cb123SKonstantin Varlamov std::array input = {1, 8, 2, 3, 4, 6, 5, 7};
208*732cb123SKonstantin Varlamov for (int i = 0; i <= static_cast<int>(input.size()); ++i){
209*732cb123SKonstantin Varlamov test_one<Iter, Sent, Out, input.size()>(input, i, gen);
210*732cb123SKonstantin Varlamov }
211*732cb123SKonstantin Varlamov }
212*732cb123SKonstantin Varlamov }
213*732cb123SKonstantin Varlamov
214*732cb123SKonstantin Varlamov template <class Iter, class Sent>
test_iterators_iter_sent()215*732cb123SKonstantin Varlamov void test_iterators_iter_sent() {
216*732cb123SKonstantin Varlamov if constexpr (std::forward_iterator<Iter>) {
217*732cb123SKonstantin Varlamov test_iterators_iter_sent_out<Iter, Sent, cpp20_output_iterator<int*>>();
218*732cb123SKonstantin Varlamov test_iterators_iter_sent_out<Iter, Sent, forward_iterator<int*>>();
219*732cb123SKonstantin Varlamov }
220*732cb123SKonstantin Varlamov test_iterators_iter_sent_out<Iter, Sent, random_access_iterator<int*>>();
221*732cb123SKonstantin Varlamov test_iterators_iter_sent_out<Iter, Sent, contiguous_iterator<int*>>();
222*732cb123SKonstantin Varlamov test_iterators_iter_sent_out<Iter, Sent, int*>();
223*732cb123SKonstantin Varlamov }
224*732cb123SKonstantin Varlamov
225*732cb123SKonstantin Varlamov template <class Iter>
test_iterators_iter()226*732cb123SKonstantin Varlamov void test_iterators_iter() {
227*732cb123SKonstantin Varlamov if constexpr (std::sentinel_for<Iter, Iter>) {
228*732cb123SKonstantin Varlamov test_iterators_iter_sent<Iter, Iter>();
229*732cb123SKonstantin Varlamov }
230*732cb123SKonstantin Varlamov test_iterators_iter_sent<Iter, sentinel_wrapper<Iter>>();
231*732cb123SKonstantin Varlamov }
232*732cb123SKonstantin Varlamov
test_iterators()233*732cb123SKonstantin Varlamov void test_iterators() {
234*732cb123SKonstantin Varlamov test_iterators_iter<cpp20_input_iterator<int*>>();
235*732cb123SKonstantin Varlamov test_iterators_iter<random_access_iterator<int*>>();
236*732cb123SKonstantin Varlamov test_iterators_iter<contiguous_iterator<int*>>();
237*732cb123SKonstantin Varlamov test_iterators_iter<int*>();
238*732cb123SKonstantin Varlamov test_iterators_iter<const int*>();
239*732cb123SKonstantin Varlamov }
240*732cb123SKonstantin Varlamov
241*732cb123SKonstantin Varlamov // Checks the logic for wrapping the given iterator to make sure it works correctly regardless of the value category of
242*732cb123SKonstantin Varlamov // the given generator object.
243*732cb123SKonstantin Varlamov template <class Gen, bool CheckConst = true>
test_generator()244*732cb123SKonstantin Varlamov void test_generator() {
245*732cb123SKonstantin Varlamov std::array in = {1, 2, 3, 4, 5, 6, 7, 8};
246*732cb123SKonstantin Varlamov constexpr int N = 5;
247*732cb123SKonstantin Varlamov std::array<int, N> output;
248*732cb123SKonstantin Varlamov auto begin = in.begin();
249*732cb123SKonstantin Varlamov auto end = in.end();
250*732cb123SKonstantin Varlamov auto out = output.begin();
251*732cb123SKonstantin Varlamov
252*732cb123SKonstantin Varlamov { // Lvalue.
253*732cb123SKonstantin Varlamov Gen g;
254*732cb123SKonstantin Varlamov std::ranges::sample(begin, end, out, N, g);
255*732cb123SKonstantin Varlamov std::ranges::sample(in, out, N, g);
256*732cb123SKonstantin Varlamov }
257*732cb123SKonstantin Varlamov
258*732cb123SKonstantin Varlamov if constexpr (CheckConst) { // Const lvalue.
259*732cb123SKonstantin Varlamov const Gen g;
260*732cb123SKonstantin Varlamov std::ranges::sample(begin, end, out, N, g);
261*732cb123SKonstantin Varlamov std::ranges::sample(in, out, N, g);
262*732cb123SKonstantin Varlamov }
263*732cb123SKonstantin Varlamov
264*732cb123SKonstantin Varlamov { // Prvalue.
265*732cb123SKonstantin Varlamov std::ranges::sample(begin, end, out, N, Gen());
266*732cb123SKonstantin Varlamov std::ranges::sample(in, out, N, Gen());
267*732cb123SKonstantin Varlamov }
268*732cb123SKonstantin Varlamov
269*732cb123SKonstantin Varlamov { // Xvalue.
270*732cb123SKonstantin Varlamov Gen g1, g2;
271*732cb123SKonstantin Varlamov std::ranges::sample(begin, end, out, N, std::move(g1));
272*732cb123SKonstantin Varlamov std::ranges::sample(in, out, N, std::move(g2));
273*732cb123SKonstantin Varlamov }
274*732cb123SKonstantin Varlamov }
275*732cb123SKonstantin Varlamov
276*732cb123SKonstantin Varlamov // Checks the logic for wrapping the given iterator to make sure it works correctly regardless of whether the given
277*732cb123SKonstantin Varlamov // generator class has a const or non-const invocation operator (or both).
test_generators()278*732cb123SKonstantin Varlamov void test_generators() {
279*732cb123SKonstantin Varlamov struct GenBase {
280*732cb123SKonstantin Varlamov constexpr static size_t min() { return 0; }
281*732cb123SKonstantin Varlamov constexpr static size_t max() { return 255; }
282*732cb123SKonstantin Varlamov };
283*732cb123SKonstantin Varlamov struct NonconstGen : GenBase {
284*732cb123SKonstantin Varlamov size_t operator()() { return 1; }
285*732cb123SKonstantin Varlamov };
286*732cb123SKonstantin Varlamov struct ConstGen : GenBase {
287*732cb123SKonstantin Varlamov size_t operator()() const { return 1; }
288*732cb123SKonstantin Varlamov };
289*732cb123SKonstantin Varlamov struct ConstAndNonconstGen : GenBase {
290*732cb123SKonstantin Varlamov size_t operator()() { return 1; }
291*732cb123SKonstantin Varlamov size_t operator()() const { return 1; }
292*732cb123SKonstantin Varlamov };
293*732cb123SKonstantin Varlamov
294*732cb123SKonstantin Varlamov test_generator<ConstGen>();
295*732cb123SKonstantin Varlamov test_generator<NonconstGen, /*CheckConst=*/false>();
296*732cb123SKonstantin Varlamov test_generator<ConstAndNonconstGen>();
297*732cb123SKonstantin Varlamov }
298*732cb123SKonstantin Varlamov
test()299*732cb123SKonstantin Varlamov void test() {
300*732cb123SKonstantin Varlamov test_iterators();
301*732cb123SKonstantin Varlamov test_generators();
302*732cb123SKonstantin Varlamov
303*732cb123SKonstantin Varlamov { // Stable (if `I` models `forward_iterator`).
304*732cb123SKonstantin Varlamov struct OrderedValue {
305*732cb123SKonstantin Varlamov int value;
306*732cb123SKonstantin Varlamov int original_order;
307*732cb123SKonstantin Varlamov bool operator==(const OrderedValue&) const = default;
308*732cb123SKonstantin Varlamov auto operator<=>(const OrderedValue& rhs) const { return value <=> rhs.value; }
309*732cb123SKonstantin Varlamov };
310*732cb123SKonstantin Varlamov
311*732cb123SKonstantin Varlamov const std::array<OrderedValue, 8> in = {{
312*732cb123SKonstantin Varlamov {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}
313*732cb123SKonstantin Varlamov }};
314*732cb123SKonstantin Varlamov
315*732cb123SKonstantin Varlamov { // (iterator, sentinel) overload.
316*732cb123SKonstantin Varlamov std::array<OrderedValue, in.size()> out;
317*732cb123SKonstantin Varlamov std::ranges::sample(in.begin(), in.end(), out.begin(), in.size(), RandGen());
318*732cb123SKonstantin Varlamov assert(out == in);
319*732cb123SKonstantin Varlamov }
320*732cb123SKonstantin Varlamov
321*732cb123SKonstantin Varlamov { // (range) overload.
322*732cb123SKonstantin Varlamov std::array<OrderedValue, in.size()> out;
323*732cb123SKonstantin Varlamov std::ranges::sample(in, out.begin(), in.size(), RandGen());
324*732cb123SKonstantin Varlamov assert(out == in);
325*732cb123SKonstantin Varlamov }
326*732cb123SKonstantin Varlamov }
327*732cb123SKonstantin Varlamov }
328*732cb123SKonstantin Varlamov
main(int,char **)329*732cb123SKonstantin Varlamov int main(int, char**) {
330*732cb123SKonstantin Varlamov test();
331*732cb123SKonstantin Varlamov // Note: `ranges::sample` is not `constexpr`.
332*732cb123SKonstantin Varlamov
333*732cb123SKonstantin Varlamov return 0;
334*732cb123SKonstantin Varlamov }
335