16bdb6422SKonstantin Varlamov //===----------------------------------------------------------------------===//
26bdb6422SKonstantin Varlamov //
36bdb6422SKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
46bdb6422SKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information.
56bdb6422SKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66bdb6422SKonstantin Varlamov //
76bdb6422SKonstantin Varlamov //===----------------------------------------------------------------------===//
86bdb6422SKonstantin Varlamov 
96bdb6422SKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17
106bdb6422SKonstantin Varlamov 
116bdb6422SKonstantin Varlamov // <algorithm>
126bdb6422SKonstantin Varlamov 
136bdb6422SKonstantin Varlamov // template<input_iterator I, sentinel_for<I> S, weakly_incrementable O, class Gen>
146bdb6422SKonstantin Varlamov //   requires (forward_iterator<I> || random_access_iterator<O>) &&
156bdb6422SKonstantin Varlamov //           indirectly_copyable<I, O> &&
166bdb6422SKonstantin Varlamov //           uniform_random_bit_generator<remove_reference_t<Gen>>
176bdb6422SKonstantin Varlamov //   O sample(I first, S last, O out, iter_difference_t<I> n, Gen&& g);                              // Since C++20
186bdb6422SKonstantin Varlamov //
196bdb6422SKonstantin Varlamov // template<input_range R, weakly_incrementable O, class Gen>
206bdb6422SKonstantin Varlamov //   requires (forward_range<R> || random_access_iterator<O>) &&
216bdb6422SKonstantin Varlamov //           indirectly_copyable<iterator_t<R>, O> &&
226bdb6422SKonstantin Varlamov //           uniform_random_bit_generator<remove_reference_t<Gen>>
236bdb6422SKonstantin Varlamov //   O sample(R&& r, O out, range_difference_t<R> n, Gen&& g);                                       // Since C++20
246bdb6422SKonstantin Varlamov 
256bdb6422SKonstantin Varlamov #include <algorithm>
266bdb6422SKonstantin Varlamov #include <array>
276bdb6422SKonstantin Varlamov #include <concepts>
286bdb6422SKonstantin Varlamov #include <functional>
296bdb6422SKonstantin Varlamov #include <random>
306bdb6422SKonstantin Varlamov #include <ranges>
316bdb6422SKonstantin Varlamov #include <utility>
326bdb6422SKonstantin Varlamov 
336bdb6422SKonstantin Varlamov #include "almost_satisfies_types.h"
346bdb6422SKonstantin Varlamov #include "test_iterators.h"
356bdb6422SKonstantin Varlamov #include "test_macros.h"
366bdb6422SKonstantin Varlamov 
376bdb6422SKonstantin Varlamov class RandGen {
386bdb6422SKonstantin Varlamov public:
min()39fb855eb9SMark de Wever   constexpr static std::size_t min() { return 0; }
max()40fb855eb9SMark de Wever   constexpr static std::size_t max() { return 255; }
416bdb6422SKonstantin Varlamov 
operator ()()42fb855eb9SMark de Wever   constexpr std::size_t operator()() {
436bdb6422SKonstantin Varlamov     flip = !flip;
446bdb6422SKonstantin Varlamov     return flip;
456bdb6422SKonstantin Varlamov   }
466bdb6422SKonstantin Varlamov 
476bdb6422SKonstantin Varlamov private:
486bdb6422SKonstantin Varlamov   bool flip = false;
496bdb6422SKonstantin Varlamov };
506bdb6422SKonstantin Varlamov 
516bdb6422SKonstantin Varlamov static_assert(std::uniform_random_bit_generator<RandGen>);
526bdb6422SKonstantin Varlamov // `std::uniform_random_bit_generator` is a subset of requirements of `__libcpp_random_is_valid_urng`. Make sure that
536bdb6422SKonstantin Varlamov // a type satisfying the required minimum is still accepted by `ranges::shuffle`.
546bdb6422SKonstantin Varlamov LIBCPP_STATIC_ASSERT(!std::__libcpp_random_is_valid_urng<RandGen>::value);
556bdb6422SKonstantin Varlamov 
566bdb6422SKonstantin Varlamov struct BadGen {
minBadGen57fb855eb9SMark de Wever   constexpr static std::size_t min() { return 255; }
maxBadGen58fb855eb9SMark de Wever   constexpr static std::size_t max() { return 0; }
59fb855eb9SMark de Wever   constexpr std::size_t operator()() const;
606bdb6422SKonstantin Varlamov };
616bdb6422SKonstantin Varlamov static_assert(!std::uniform_random_bit_generator<BadGen>);
626bdb6422SKonstantin Varlamov 
636bdb6422SKonstantin Varlamov // Test constraints of the (iterator, sentinel) overload.
646bdb6422SKonstantin Varlamov // ======================================================
656bdb6422SKonstantin Varlamov 
666bdb6422SKonstantin Varlamov template <class Iter = int*, class Sent = int*, class Out = int*, class Gen = RandGen>
676bdb6422SKonstantin Varlamov concept HasSampleIter =
686bdb6422SKonstantin Varlamov     requires(Iter&& iter, Sent&& sent, Out&& out, std::iter_difference_t<Iter> n, Gen&& gen) {
696bdb6422SKonstantin Varlamov       std::ranges::sample(std::forward<Iter>(iter), std::forward<Sent>(sent),
706bdb6422SKonstantin Varlamov                           std::forward<Out>(out), n, std::forward<Gen>(gen));
716bdb6422SKonstantin Varlamov     };
726bdb6422SKonstantin Varlamov 
736bdb6422SKonstantin Varlamov static_assert(HasSampleIter<int*, int*, int*, RandGen>);
746bdb6422SKonstantin Varlamov 
756bdb6422SKonstantin Varlamov // !input_iterator<I>
766bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<InputIteratorNotDerivedFrom>);
776bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<InputIteratorNotIndirectlyReadable>);
786bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<InputIteratorNotInputOrOutputIterator>);
796bdb6422SKonstantin Varlamov 
806bdb6422SKonstantin Varlamov // !sentinel_for<S, I>
816bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<int*, SentinelForNotSemiregular>);
826bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<int*, SentinelForNotWeaklyEqualityComparableWith>);
836bdb6422SKonstantin Varlamov 
846bdb6422SKonstantin Varlamov // !weakly_incrementable<O>
856bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<int*, int*, WeaklyIncrementableNotMovable>);
866bdb6422SKonstantin Varlamov 
876bdb6422SKonstantin Varlamov // (forward_iterator<I> || random_access_iterator<O>)
886bdb6422SKonstantin Varlamov static_assert(HasSampleIter<
896bdb6422SKonstantin Varlamov     forward_iterator<int*>, forward_iterator<int*>,
906bdb6422SKonstantin Varlamov     cpp20_output_iterator<int*>
916bdb6422SKonstantin Varlamov >);
926bdb6422SKonstantin Varlamov static_assert(HasSampleIter<
936bdb6422SKonstantin Varlamov     cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>,
946bdb6422SKonstantin Varlamov     random_access_iterator<int*>
956bdb6422SKonstantin Varlamov >);
966bdb6422SKonstantin Varlamov // !(forward_iterator<I> || random_access_iterator<O>)
976bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<
986bdb6422SKonstantin Varlamov     cpp20_input_iterator<int*>, sentinel_wrapper<cpp20_input_iterator<int*>>,
996bdb6422SKonstantin Varlamov     cpp20_output_iterator<int*>
1006bdb6422SKonstantin Varlamov >);
1016bdb6422SKonstantin Varlamov 
1026bdb6422SKonstantin Varlamov // !indirectly_copyable<I, O>
1036bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<int*, int*, int**>);
1046bdb6422SKonstantin Varlamov 
1056bdb6422SKonstantin Varlamov // !uniform_random_bit_generator<remove_reference_t<Gen>>
1066bdb6422SKonstantin Varlamov static_assert(!HasSampleIter<int*, int*, int*, BadGen>);
1076bdb6422SKonstantin Varlamov 
1086bdb6422SKonstantin Varlamov // Test constraints of the (range) overload.
1096bdb6422SKonstantin Varlamov // =========================================
1106bdb6422SKonstantin Varlamov 
1116bdb6422SKonstantin Varlamov template <class Range, class Out = int*, class Gen = RandGen>
1126bdb6422SKonstantin Varlamov concept HasSampleRange =
1136bdb6422SKonstantin Varlamov     requires(Range&& range, Out&& out, std::ranges::range_difference_t<Range> n, Gen&& gen) {
1146bdb6422SKonstantin Varlamov       std::ranges::sample(std::forward<Range>(range), std::forward<Out>(out), n, std::forward<Gen>(gen));
1156bdb6422SKonstantin Varlamov     };
1166bdb6422SKonstantin Varlamov 
1176bdb6422SKonstantin Varlamov template <class T>
1186bdb6422SKonstantin Varlamov using R = UncheckedRange<T>;
1196bdb6422SKonstantin Varlamov 
1206bdb6422SKonstantin Varlamov static_assert(HasSampleRange<R<int*>, int*, RandGen>);
1216bdb6422SKonstantin Varlamov 
1226bdb6422SKonstantin Varlamov // !input_range<R>
1236bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<InputRangeNotDerivedFrom>);
1246bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<InputRangeNotIndirectlyReadable>);
1256bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<InputRangeNotInputOrOutputIterator>);
1266bdb6422SKonstantin Varlamov 
1276bdb6422SKonstantin Varlamov // !weakly_incrementable<O>
1286bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<R<int*>, WeaklyIncrementableNotMovable>);
1296bdb6422SKonstantin Varlamov 
1306bdb6422SKonstantin Varlamov // (forward_range<R> || random_access_iterator<O>)
1316bdb6422SKonstantin Varlamov static_assert(HasSampleRange<
1326bdb6422SKonstantin Varlamov     R<forward_iterator<int*>>,
1336bdb6422SKonstantin Varlamov     cpp20_output_iterator<int*>
1346bdb6422SKonstantin Varlamov >);
1356bdb6422SKonstantin Varlamov static_assert(HasSampleRange<
1366bdb6422SKonstantin Varlamov     R<cpp20_input_iterator<int*>>,
1376bdb6422SKonstantin Varlamov     random_access_iterator<int*>
1386bdb6422SKonstantin Varlamov >);
1396bdb6422SKonstantin Varlamov // !(forward_range<R> || random_access_iterator<O>)
1406bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<
1416bdb6422SKonstantin Varlamov     R<cpp20_input_iterator<int*>>,
1426bdb6422SKonstantin Varlamov     cpp20_output_iterator<int*>
1436bdb6422SKonstantin Varlamov >);
1446bdb6422SKonstantin Varlamov 
1456bdb6422SKonstantin Varlamov // !indirectly_copyable<I, O>
1466bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<R<int*>, int**>);
1476bdb6422SKonstantin Varlamov 
1486bdb6422SKonstantin Varlamov // !uniform_random_bit_generator<remove_reference_t<Gen>>
1496bdb6422SKonstantin Varlamov static_assert(!HasSampleRange<R<int*>, int*, BadGen>);
1506bdb6422SKonstantin Varlamov 
151fb855eb9SMark de Wever template <class Iter, class Sent, class Out, std::size_t N, class Gen>
test_one(std::array<int,N> in,std::size_t n,Gen gen)152fb855eb9SMark de Wever void test_one(std::array<int, N> in, std::size_t n, Gen gen) {
153fb855eb9SMark de Wever   assert(n <= static_cast<std::size_t>(N));
1546bdb6422SKonstantin Varlamov 
1556bdb6422SKonstantin Varlamov   auto verify_is_subsequence = [&] (auto output) {
1566bdb6422SKonstantin Varlamov     auto sorted_input = in;
1576bdb6422SKonstantin Varlamov     std::ranges::sort(sorted_input);
1586bdb6422SKonstantin Varlamov     auto sorted_output = std::ranges::subrange(output.begin(), output.begin() + n);
1596bdb6422SKonstantin Varlamov     std::ranges::sort(sorted_output);
1606bdb6422SKonstantin Varlamov     assert(std::ranges::includes(sorted_input, sorted_output));
1616bdb6422SKonstantin Varlamov   };
1626bdb6422SKonstantin Varlamov 
1636bdb6422SKonstantin Varlamov   { // (iterator, sentinel) overload.
1646bdb6422SKonstantin Varlamov     auto begin = Iter(in.data());
1656bdb6422SKonstantin Varlamov     auto end = Sent(Iter(in.data() + in.size()));
1666bdb6422SKonstantin Varlamov     std::array<int, N> output;
167*d05bada5SDuo Wang     auto out = Out(output.data());
1686bdb6422SKonstantin Varlamov 
1696bdb6422SKonstantin Varlamov     std::same_as<Out> decltype(auto) result = std::ranges::sample(
1706bdb6422SKonstantin Varlamov         std::move(begin), std::move(end), std::move(out), n, gen);
1716bdb6422SKonstantin Varlamov     assert(base(result) == output.data() + n);
1726bdb6422SKonstantin Varlamov     verify_is_subsequence(output);
1736bdb6422SKonstantin Varlamov     // The output of `sample` is implementation-specific.
1746bdb6422SKonstantin Varlamov   }
1756bdb6422SKonstantin Varlamov 
1766bdb6422SKonstantin Varlamov   { // (range) overload.
1776bdb6422SKonstantin Varlamov     auto begin = Iter(in.data());
1786bdb6422SKonstantin Varlamov     auto end = Sent(Iter(in.data() + in.size()));
1796bdb6422SKonstantin Varlamov     std::array<int, N> output;
180*d05bada5SDuo Wang     auto out = Out(output.data());
1816bdb6422SKonstantin Varlamov 
1826bdb6422SKonstantin Varlamov     std::same_as<Out> decltype(auto) result = std::ranges::sample(std::ranges::subrange(
1836bdb6422SKonstantin Varlamov         std::move(begin), std::move(end)), std::move(out), n, gen);
1846bdb6422SKonstantin Varlamov     assert(base(result) == output.data() + n);
1856bdb6422SKonstantin Varlamov     verify_is_subsequence(output);
1866bdb6422SKonstantin Varlamov     // The output of `sample` is implementation-specific.
1876bdb6422SKonstantin Varlamov   }
1886bdb6422SKonstantin Varlamov }
1896bdb6422SKonstantin Varlamov 
1906bdb6422SKonstantin Varlamov template <class Iter, class Sent, class Out>
test_iterators_iter_sent_out()1916bdb6422SKonstantin Varlamov void test_iterators_iter_sent_out() {
1926bdb6422SKonstantin Varlamov   RandGen gen;
1936bdb6422SKonstantin Varlamov 
1946bdb6422SKonstantin Varlamov   // Empty sequence.
1956bdb6422SKonstantin Varlamov   test_one<Iter, Sent, Out, 0>({}, 0, gen);
1966bdb6422SKonstantin Varlamov   // 1-element sequence.
1976bdb6422SKonstantin Varlamov   test_one<Iter, Sent, Out, 1>({1}, 1, gen);
1986bdb6422SKonstantin Varlamov   // 2-element sequence.
1996bdb6422SKonstantin Varlamov   test_one<Iter, Sent, Out, 2>({1, 2}, 1, gen);
2006bdb6422SKonstantin Varlamov   test_one<Iter, Sent, Out, 2>({1, 2}, 2, gen);
2016bdb6422SKonstantin Varlamov   // n == 0.
2026bdb6422SKonstantin Varlamov   test_one<Iter, Sent, Out, 3>({1, 2, 3}, 0, gen);
2036bdb6422SKonstantin Varlamov 
2046bdb6422SKonstantin Varlamov   // Longer sequence.
2056bdb6422SKonstantin Varlamov   {
2066bdb6422SKonstantin Varlamov     std::array input = {1, 8, 2, 3, 4, 6, 5, 7};
2076bdb6422SKonstantin Varlamov     for (int i = 0; i <= static_cast<int>(input.size()); ++i){
2086bdb6422SKonstantin Varlamov       test_one<Iter, Sent, Out, input.size()>(input, i, gen);
2096bdb6422SKonstantin Varlamov     }
2106bdb6422SKonstantin Varlamov   }
2116bdb6422SKonstantin Varlamov }
2126bdb6422SKonstantin Varlamov 
2136bdb6422SKonstantin Varlamov template <class Iter, class Sent>
test_iterators_iter_sent()2146bdb6422SKonstantin Varlamov void test_iterators_iter_sent() {
2156bdb6422SKonstantin Varlamov   if constexpr (std::forward_iterator<Iter>) {
2166bdb6422SKonstantin Varlamov     test_iterators_iter_sent_out<Iter, Sent, cpp20_output_iterator<int*>>();
2176bdb6422SKonstantin Varlamov     test_iterators_iter_sent_out<Iter, Sent, forward_iterator<int*>>();
2186bdb6422SKonstantin Varlamov   }
2196bdb6422SKonstantin Varlamov   test_iterators_iter_sent_out<Iter, Sent, random_access_iterator<int*>>();
2206bdb6422SKonstantin Varlamov   test_iterators_iter_sent_out<Iter, Sent, contiguous_iterator<int*>>();
2216bdb6422SKonstantin Varlamov   test_iterators_iter_sent_out<Iter, Sent, int*>();
2226bdb6422SKonstantin Varlamov }
2236bdb6422SKonstantin Varlamov 
2246bdb6422SKonstantin Varlamov template <class Iter>
test_iterators_iter()2256bdb6422SKonstantin Varlamov void test_iterators_iter() {
2266bdb6422SKonstantin Varlamov   if constexpr (std::sentinel_for<Iter, Iter>) {
2276bdb6422SKonstantin Varlamov     test_iterators_iter_sent<Iter, Iter>();
2286bdb6422SKonstantin Varlamov   }
2296bdb6422SKonstantin Varlamov   test_iterators_iter_sent<Iter, sentinel_wrapper<Iter>>();
2306bdb6422SKonstantin Varlamov }
2316bdb6422SKonstantin Varlamov 
test_iterators()2326bdb6422SKonstantin Varlamov void test_iterators() {
2336bdb6422SKonstantin Varlamov   test_iterators_iter<cpp20_input_iterator<int*>>();
2346bdb6422SKonstantin Varlamov   test_iterators_iter<random_access_iterator<int*>>();
2356bdb6422SKonstantin Varlamov   test_iterators_iter<contiguous_iterator<int*>>();
2366bdb6422SKonstantin Varlamov   test_iterators_iter<int*>();
2376bdb6422SKonstantin Varlamov   test_iterators_iter<const int*>();
2386bdb6422SKonstantin Varlamov }
2396bdb6422SKonstantin Varlamov 
2406bdb6422SKonstantin Varlamov // Checks the logic for wrapping the given iterator to make sure it works correctly regardless of the value category of
2416bdb6422SKonstantin Varlamov // the given generator object.
2426bdb6422SKonstantin Varlamov template <class Gen, bool CheckConst = true>
test_generator()2436bdb6422SKonstantin Varlamov void test_generator() {
2446bdb6422SKonstantin Varlamov   std::array in = {1, 2, 3, 4, 5, 6, 7, 8};
2456bdb6422SKonstantin Varlamov   constexpr int N = 5;
2466bdb6422SKonstantin Varlamov   std::array<int, N> output;
2476bdb6422SKonstantin Varlamov   auto begin = in.begin();
2486bdb6422SKonstantin Varlamov   auto end = in.end();
2496bdb6422SKonstantin Varlamov   auto out = output.begin();
2506bdb6422SKonstantin Varlamov 
2516bdb6422SKonstantin Varlamov   { // Lvalue.
2526bdb6422SKonstantin Varlamov     Gen g;
2536bdb6422SKonstantin Varlamov     std::ranges::sample(begin, end, out, N, g);
2546bdb6422SKonstantin Varlamov     std::ranges::sample(in, out, N, g);
2556bdb6422SKonstantin Varlamov   }
2566bdb6422SKonstantin Varlamov 
2576bdb6422SKonstantin Varlamov   if constexpr (CheckConst) { // Const lvalue.
2586bdb6422SKonstantin Varlamov     const Gen g;
2596bdb6422SKonstantin Varlamov     std::ranges::sample(begin, end, out, N, g);
2606bdb6422SKonstantin Varlamov     std::ranges::sample(in, out, N, g);
2616bdb6422SKonstantin Varlamov   }
2626bdb6422SKonstantin Varlamov 
2636bdb6422SKonstantin Varlamov   { // Prvalue.
2646bdb6422SKonstantin Varlamov     std::ranges::sample(begin, end, out, N, Gen());
2656bdb6422SKonstantin Varlamov     std::ranges::sample(in, out, N, Gen());
2666bdb6422SKonstantin Varlamov   }
2676bdb6422SKonstantin Varlamov 
2686bdb6422SKonstantin Varlamov   { // Xvalue.
2696bdb6422SKonstantin Varlamov     Gen g1, g2;
2706bdb6422SKonstantin Varlamov     std::ranges::sample(begin, end, out, N, std::move(g1));
2716bdb6422SKonstantin Varlamov     std::ranges::sample(in, out, N, std::move(g2));
2726bdb6422SKonstantin Varlamov   }
2736bdb6422SKonstantin Varlamov }
2746bdb6422SKonstantin Varlamov 
2756bdb6422SKonstantin Varlamov // Checks the logic for wrapping the given iterator to make sure it works correctly regardless of whether the given
2766bdb6422SKonstantin Varlamov // generator class has a const or non-const invocation operator (or both).
test_generators()2776bdb6422SKonstantin Varlamov void test_generators() {
2786bdb6422SKonstantin Varlamov   struct GenBase {
279fb855eb9SMark de Wever     constexpr static std::size_t min() { return 0; }
280fb855eb9SMark de Wever     constexpr static std::size_t max() { return 255; }
2816bdb6422SKonstantin Varlamov   };
2826bdb6422SKonstantin Varlamov   struct NonconstGen : GenBase {
283fb855eb9SMark de Wever     std::size_t operator()() { return 1; }
2846bdb6422SKonstantin Varlamov   };
2856bdb6422SKonstantin Varlamov   struct ConstGen : GenBase {
286fb855eb9SMark de Wever     std::size_t operator()() const { return 1; }
2876bdb6422SKonstantin Varlamov   };
2886bdb6422SKonstantin Varlamov   struct ConstAndNonconstGen : GenBase {
289fb855eb9SMark de Wever     std::size_t operator()() { return 1; }
290fb855eb9SMark de Wever     std::size_t operator()() const { return 1; }
2916bdb6422SKonstantin Varlamov   };
2926bdb6422SKonstantin Varlamov 
2936bdb6422SKonstantin Varlamov   test_generator<ConstGen>();
2946bdb6422SKonstantin Varlamov   test_generator<NonconstGen, /*CheckConst=*/false>();
2956bdb6422SKonstantin Varlamov   test_generator<ConstAndNonconstGen>();
2966bdb6422SKonstantin Varlamov }
2976bdb6422SKonstantin Varlamov 
test()2986bdb6422SKonstantin Varlamov void test() {
2996bdb6422SKonstantin Varlamov   test_iterators();
3006bdb6422SKonstantin Varlamov   test_generators();
3016bdb6422SKonstantin Varlamov 
3026bdb6422SKonstantin Varlamov   { // Stable (if `I` models `forward_iterator`).
3036bdb6422SKonstantin Varlamov     struct OrderedValue {
3046bdb6422SKonstantin Varlamov       int value;
3056bdb6422SKonstantin Varlamov       int original_order;
3066bdb6422SKonstantin Varlamov       bool operator==(const OrderedValue&) const = default;
3076bdb6422SKonstantin Varlamov       auto operator<=>(const OrderedValue& rhs) const { return value <=> rhs.value; }
3086bdb6422SKonstantin Varlamov     };
3096bdb6422SKonstantin Varlamov 
3106bdb6422SKonstantin Varlamov     const std::array<OrderedValue, 8> in = {{
3116bdb6422SKonstantin Varlamov       {1, 1}, {1, 2}, {1, 3}, {1, 4}, {1, 5}, {1, 6}, {1, 7}, {1, 8}
3126bdb6422SKonstantin Varlamov     }};
3136bdb6422SKonstantin Varlamov 
3146bdb6422SKonstantin Varlamov     { // (iterator, sentinel) overload.
3156bdb6422SKonstantin Varlamov       std::array<OrderedValue, in.size()> out;
3166bdb6422SKonstantin Varlamov       std::ranges::sample(in.begin(), in.end(), out.begin(), in.size(), RandGen());
3176bdb6422SKonstantin Varlamov       assert(out == in);
3186bdb6422SKonstantin Varlamov     }
3196bdb6422SKonstantin Varlamov 
3206bdb6422SKonstantin Varlamov     { // (range) overload.
3216bdb6422SKonstantin Varlamov       std::array<OrderedValue, in.size()> out;
3226bdb6422SKonstantin Varlamov       std::ranges::sample(in, out.begin(), in.size(), RandGen());
3236bdb6422SKonstantin Varlamov       assert(out == in);
3246bdb6422SKonstantin Varlamov     }
3256bdb6422SKonstantin Varlamov   }
3266bdb6422SKonstantin Varlamov }
3276bdb6422SKonstantin Varlamov 
main(int,char **)3286bdb6422SKonstantin Varlamov int main(int, char**) {
3296bdb6422SKonstantin Varlamov   test();
3306bdb6422SKonstantin Varlamov   // Note: `ranges::sample` is not `constexpr`.
3316bdb6422SKonstantin Varlamov 
3326bdb6422SKonstantin Varlamov   return 0;
3336bdb6422SKonstantin Varlamov }
334