1*61cfbce3SDimitry Andric //===----------------------------------------------------------------------===//
2*61cfbce3SDimitry Andric //
3*61cfbce3SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*61cfbce3SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*61cfbce3SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*61cfbce3SDimitry Andric //
7*61cfbce3SDimitry Andric //===----------------------------------------------------------------------===//
8*61cfbce3SDimitry Andric 
9*61cfbce3SDimitry Andric #ifndef _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H
10*61cfbce3SDimitry Andric #define _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H
11*61cfbce3SDimitry Andric 
12*61cfbce3SDimitry Andric #include <__config>
13*61cfbce3SDimitry Andric #include <__functional/invoke.h>
14*61cfbce3SDimitry Andric #include <type_traits>
15*61cfbce3SDimitry Andric 
16*61cfbce3SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17*61cfbce3SDimitry Andric #  pragma GCC system_header
18*61cfbce3SDimitry Andric #endif
19*61cfbce3SDimitry Andric 
20*61cfbce3SDimitry Andric #if _LIBCPP_STD_VER > 17
21*61cfbce3SDimitry Andric 
22*61cfbce3SDimitry Andric _LIBCPP_PUSH_MACROS
23*61cfbce3SDimitry Andric #include <__undef_macros>
24*61cfbce3SDimitry Andric 
25*61cfbce3SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
26*61cfbce3SDimitry Andric 
27*61cfbce3SDimitry Andric // Range versions of random algorithms (e.g. `std::shuffle`) are less constrained than their classic counterparts.
28*61cfbce3SDimitry Andric // Range algorithms only require the given generator to satisfy the `std::uniform_random_bit_generator` concept.
29*61cfbce3SDimitry Andric // Classic algorithms require the given generator to meet the uniform random bit generator requirements; these
30*61cfbce3SDimitry Andric // requirements include satisfying `std::uniform_random_bit_generator` and add a requirement for the generator to
31*61cfbce3SDimitry Andric // provide a nested `result_type` typedef (see `[rand.req.urng]`).
32*61cfbce3SDimitry Andric //
33*61cfbce3SDimitry Andric // To be able to reuse classic implementations, make the given generator meet the classic requirements by wrapping
34*61cfbce3SDimitry Andric // it into an adaptor type that forwards all of its interface and adds the required typedef.
35*61cfbce3SDimitry Andric template <class _Gen>
36*61cfbce3SDimitry Andric class _ClassicGenAdaptor {
37*61cfbce3SDimitry Andric private:
38*61cfbce3SDimitry Andric   // The generator is not required to be copyable or movable, so it has to be stored as a reference.
39*61cfbce3SDimitry Andric   _Gen& __gen;
40*61cfbce3SDimitry Andric 
41*61cfbce3SDimitry Andric public:
42*61cfbce3SDimitry Andric   using result_type = invoke_result_t<_Gen&>;
43*61cfbce3SDimitry Andric 
44*61cfbce3SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
45*61cfbce3SDimitry Andric   static constexpr auto min() { return __uncvref_t<_Gen>::min(); }
46*61cfbce3SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
47*61cfbce3SDimitry Andric   static constexpr auto max() { return __uncvref_t<_Gen>::max(); }
48*61cfbce3SDimitry Andric 
49*61cfbce3SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
50*61cfbce3SDimitry Andric   constexpr explicit _ClassicGenAdaptor(_Gen& __g) : __gen(__g) {}
51*61cfbce3SDimitry Andric 
52*61cfbce3SDimitry Andric   _LIBCPP_HIDE_FROM_ABI
53*61cfbce3SDimitry Andric   constexpr auto operator()() const { return __gen(); }
54*61cfbce3SDimitry Andric };
55*61cfbce3SDimitry Andric 
56*61cfbce3SDimitry Andric _LIBCPP_END_NAMESPACE_STD
57*61cfbce3SDimitry Andric 
58*61cfbce3SDimitry Andric _LIBCPP_POP_MACROS
59*61cfbce3SDimitry Andric 
60*61cfbce3SDimitry Andric #endif // _LIBCPP_STD_VER > 17
61*61cfbce3SDimitry Andric 
62*61cfbce3SDimitry Andric #endif // _LIBCPP___ALGORITHM_RANGES_UNIFORM_RANDOM_BIT_GENERATOR_ADAPTOR_H
63