File indexing completed on 2025-01-18 09:27:21
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #ifndef ABSL_RANDOM_BIT_GEN_REF_H_
0025 #define ABSL_RANDOM_BIT_GEN_REF_H_
0026
0027 #include <limits>
0028 #include <type_traits>
0029 #include <utility>
0030
0031 #include "absl/base/attributes.h"
0032 #include "absl/base/internal/fast_type_id.h"
0033 #include "absl/base/macros.h"
0034 #include "absl/meta/type_traits.h"
0035 #include "absl/random/internal/distribution_caller.h"
0036 #include "absl/random/internal/fast_uniform_bits.h"
0037
0038 namespace absl {
0039 ABSL_NAMESPACE_BEGIN
0040 namespace random_internal {
0041
0042 template <typename URBG, typename = void, typename = void, typename = void>
0043 struct is_urbg : std::false_type {};
0044
0045 template <typename URBG>
0046 struct is_urbg<
0047 URBG,
0048 absl::enable_if_t<std::is_same<
0049 typename URBG::result_type,
0050 typename std::decay<decltype((URBG::min)())>::type>::value>,
0051 absl::enable_if_t<std::is_same<
0052 typename URBG::result_type,
0053 typename std::decay<decltype((URBG::max)())>::type>::value>,
0054 absl::enable_if_t<std::is_same<
0055 typename URBG::result_type,
0056 typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
0057 : std::true_type {};
0058
0059 template <typename>
0060 struct DistributionCaller;
0061 class MockHelpers;
0062
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088 class BitGenRef {
0089
0090
0091
0092
0093
0094 template <template <class...> class Trait, class AlwaysVoid, class... Args>
0095 struct detector : std::false_type {};
0096 template <template <class...> class Trait, class... Args>
0097 struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
0098 : std::true_type {};
0099
0100 template <class T>
0101 using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
0102 std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
0103 std::declval<void*>()));
0104
0105 template <typename T>
0106 using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
0107
0108 public:
0109 BitGenRef(const BitGenRef&) = default;
0110 BitGenRef(BitGenRef&&) = default;
0111 BitGenRef& operator=(const BitGenRef&) = default;
0112 BitGenRef& operator=(BitGenRef&&) = default;
0113
0114 template <
0115 typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
0116 typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
0117 random_internal::is_urbg<URBG>::value &&
0118 !HasInvokeMock<URBG>::value)>* = nullptr>
0119 BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)
0120 : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
0121 mock_call_(NotAMock),
0122 generate_impl_fn_(ImplFn<URBG>) {}
0123
0124 template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
0125 typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
0126 random_internal::is_urbg<URBG>::value &&
0127 HasInvokeMock<URBG>::value)>* = nullptr>
0128 BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)
0129 : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
0130 mock_call_(&MockCall<URBG>),
0131 generate_impl_fn_(ImplFn<URBG>) {}
0132
0133 using result_type = uint64_t;
0134
0135 static constexpr result_type(min)() {
0136 return (std::numeric_limits<result_type>::min)();
0137 }
0138
0139 static constexpr result_type(max)() {
0140 return (std::numeric_limits<result_type>::max)();
0141 }
0142
0143 result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }
0144
0145 private:
0146 using impl_fn = result_type (*)(uintptr_t);
0147 using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
0148 void*);
0149
0150 template <typename URBG>
0151 static result_type ImplFn(uintptr_t ptr) {
0152
0153
0154 absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;
0155 return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
0156 }
0157
0158
0159 template <typename URBG>
0160 static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
0161 void* result, void* arg_tuple) {
0162 return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
0163 arg_tuple);
0164 }
0165 static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
0166 return false;
0167 }
0168
0169 inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
0170 void* result) {
0171 if (mock_call_ == NotAMock) return false;
0172 return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
0173 }
0174
0175 uintptr_t t_erased_gen_ptr_;
0176 mock_call_fn mock_call_;
0177 impl_fn generate_impl_fn_;
0178
0179 template <typename>
0180 friend struct ::absl::random_internal::DistributionCaller;
0181 friend class ::absl::random_internal::MockHelpers;
0182 };
0183
0184 ABSL_NAMESPACE_END
0185 }
0186
0187 #endif