xref: /freebsd-src/contrib/llvm-project/libcxx/include/__algorithm/ranges_shuffle.h (revision 972a253a57b6f144b0e4a3e2080a2a0076ec55a0)
1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H
10 #define _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H
11 
12 #include <__algorithm/iterator_operations.h>
13 #include <__algorithm/shuffle.h>
14 #include <__config>
15 #include <__functional/invoke.h>
16 #include <__functional/ranges_operations.h>
17 #include <__iterator/concepts.h>
18 #include <__iterator/iterator_traits.h>
19 #include <__iterator/next.h>
20 #include <__iterator/permutable.h>
21 #include <__random/uniform_random_bit_generator.h>
22 #include <__ranges/access.h>
23 #include <__ranges/concepts.h>
24 #include <__ranges/dangling.h>
25 #include <__utility/forward.h>
26 #include <__utility/move.h>
27 #include <type_traits>
28 
29 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
30 #  pragma GCC system_header
31 #endif
32 
33 #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
34 
35 _LIBCPP_PUSH_MACROS
36 #include <__undef_macros>
37 
38 _LIBCPP_BEGIN_NAMESPACE_STD
39 
40 namespace ranges {
41 namespace __shuffle {
42 
43 struct __fn {
44   // `std::shuffle` is more constrained than `std::ranges::shuffle`. `std::ranges::shuffle` only requires the given
45   // generator to satisfy the `std::uniform_random_bit_generator` concept. `std::shuffle` requires the given
46   // generator to meet the uniform random bit generator requirements; these requirements include satisfying
47   // `std::uniform_random_bit_generator` and add a requirement for the generator to provide a nested `result_type`
48   // typedef (see `[rand.req.urng]`).
49   //
50   // To reuse the implementation from `std::shuffle`, make the given generator meet the classic requirements by wrapping
51   // it into an adaptor type that forwards all of its interface and adds the required typedef.
52   template <class _Gen>
53   class _ClassicGenAdaptor {
54   private:
55     // The generator is not required to be copyable or movable, so it has to be stored as a reference.
56     _Gen& __gen;
57 
58   public:
59     using result_type = invoke_result_t<_Gen&>;
60 
61     _LIBCPP_HIDE_FROM_ABI
62     static constexpr auto min() { return __uncvref_t<_Gen>::min(); }
63     _LIBCPP_HIDE_FROM_ABI
64     static constexpr auto max() { return __uncvref_t<_Gen>::max(); }
65 
66     _LIBCPP_HIDE_FROM_ABI
67     constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {}
68 
69     _LIBCPP_HIDE_FROM_ABI
70     constexpr auto operator()() const { return __gen(); }
71   };
72 
73   template <random_access_iterator _Iter, sentinel_for<_Iter> _Sent, class _Gen>
74   requires permutable<_Iter> && uniform_random_bit_generator<remove_reference_t<_Gen>>
75   _LIBCPP_HIDE_FROM_ABI
76   _Iter operator()(_Iter __first, _Sent __last, _Gen&& __gen) const {
77     _ClassicGenAdaptor<_Gen> __adapted_gen(__gen);
78     return std::__shuffle<_RangeAlgPolicy>(std::move(__first), std::move(__last), __adapted_gen);
79   }
80 
81   template<random_access_range _Range, class _Gen>
82   requires permutable<iterator_t<_Range>> && uniform_random_bit_generator<remove_reference_t<_Gen>>
83   _LIBCPP_HIDE_FROM_ABI
84   borrowed_iterator_t<_Range> operator()(_Range&& __range, _Gen&& __gen) const {
85     return (*this)(ranges::begin(__range), ranges::end(__range), std::forward<_Gen>(__gen));
86   }
87 
88 };
89 
90 } // namespace __shuffle
91 
92 inline namespace __cpo {
93   inline constexpr auto shuffle = __shuffle::__fn{};
94 } // namespace __cpo
95 } // namespace ranges
96 
97 _LIBCPP_END_NAMESPACE_STD
98 
99 _LIBCPP_POP_MACROS
100 
101 #endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)
102 
103 #endif // _LIBCPP___ALGORITHM_RANGES_SHUFFLE_H
104