Reduce duplication in absl/random/internal.

Consolidate the mocking requirements so that mock detection is mediated
via the MockingAccess class
* HasInvokeMock has been deduplicated; MockingAccess now owns it
* InvokeMock is done via MockingAccess::InvokeMock
* In absl::BitGenRef, if a class has a conversion operator that is used.
* `friend class MockingAccess` is now the only mocking friend, except for backwards compat.
  - friend DistributionCaller is now unnecessary.
  - friend BitGenRef is now unnecessary.
  - friend MockHelpers now unnecessary.

PiperOrigin-RevId: 889366369
Change-Id: I288cd60f6ac13b257c10ec3268d96828f1e61db6
diff --git a/absl/random/BUILD.bazel b/absl/random/BUILD.bazel
index 8986211..28f6872 100644
--- a/absl/random/BUILD.bazel
+++ b/absl/random/BUILD.bazel
@@ -128,13 +128,14 @@
     copts = ABSL_DEFAULT_COPTS,
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":mocking_access",
         ":random",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
-        "//absl/random/internal:distribution_caller",
         "//absl/random/internal:fast_uniform_bits",
+        "//absl/random/internal:traits",
     ],
 )
 
@@ -160,6 +161,7 @@
     ],
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
+        ":mocking_access",
         ":random",
         "//absl/base:config",
         "//absl/base:fast_type_id",
@@ -171,6 +173,16 @@
     ],
 )
 
+cc_library(
+    name = "mocking_access",
+    hdrs = ["mocking_access.h"],
+    deps = [
+        "//absl/base:config",
+        "//absl/base:fast_type_id",
+        "//absl/meta:type_traits",
+    ],
+)
+
 cc_test(
     name = "bernoulli_distribution_test",
     size = "small",
diff --git a/absl/random/CMakeLists.txt b/absl/random/CMakeLists.txt
index 7382b0d..4a13e84 100644
--- a/absl/random/CMakeLists.txt
+++ b/absl/random/CMakeLists.txt
@@ -44,9 +44,10 @@
   DEPS
     absl::config
     absl::core_headers
-    absl::random_internal_distribution_caller
     absl::random_internal_fast_uniform_bits
     absl::type_traits
+    absl::random_mocking_access
+    absl::random_internal_traits
 )
 
 absl_cc_test(
@@ -68,6 +69,21 @@
     GTest::gtest_main
 )
 
+absl_cc_library(
+  NAME
+    random_mocking_access
+  HDRS
+    "mocking_access.h"
+  COPTS
+    ${ABSL_DEFAULT_COPTS}
+  LINKOPTS
+    ${ABSL_DEFAULT_LINKOPTS}
+  DEPS
+    absl::config
+    absl::fast_type_id
+    absl::type_traits
+)
+
 # Internal-only target, do not depend on directly.
 absl_cc_library(
   NAME
@@ -82,6 +98,7 @@
     absl::config
     absl::fast_type_id
     absl::optional
+    absl::random_mocking_access
 )
 
 # Internal-only target, do not depend on directly.
@@ -118,6 +135,7 @@
     absl::flat_hash_map
     absl::raw_logging_internal
     absl::random_internal_mock_helpers
+    absl::random_mocking_access
     absl::random_random
     absl::type_traits
     absl::utility
@@ -536,6 +554,9 @@
     ${ABSL_DEFAULT_LINKOPTS}
   DEPS
     absl::config
+    absl::type_traits
+    absl::bits
+    absl::int128
 )
 
 # Internal-only target, do not depend on directly.
@@ -553,6 +574,7 @@
     absl::utility
     absl::fast_type_id
     absl::type_traits
+    absl::random_mocking_access
 )
 
 # Internal-only target, do not depend on directly.
diff --git a/absl/random/bit_gen_ref.h b/absl/random/bit_gen_ref.h
index dfce2c4..8ac4d93 100644
--- a/absl/random/bit_gen_ref.h
+++ b/absl/random/bit_gen_ref.h
@@ -27,41 +27,17 @@
 #include <cstdint>
 #include <limits>
 #include <type_traits>
-#include <utility>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/fast_type_id.h"
 #include "absl/meta/type_traits.h"
-#include "absl/random/internal/distribution_caller.h"
 #include "absl/random/internal/fast_uniform_bits.h"
+#include "absl/random/internal/traits.h"
+#include "absl/random/mocking_access.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
-namespace random_internal {
-
-template <typename URBG, typename = void, typename = void, typename = void>
-struct is_urbg : std::false_type {};
-
-template <typename URBG>
-struct is_urbg<
-    URBG,
-    absl::enable_if_t<std::is_same<
-        typename URBG::result_type,
-        typename std::decay<decltype((URBG::min)())>::type>::value>,
-    absl::enable_if_t<std::is_same<
-        typename URBG::result_type,
-        typename std::decay<decltype((URBG::max)())>::type>::value>,
-    absl::enable_if_t<std::is_same<
-        typename URBG::result_type,
-        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
-    : std::true_type {};
-
-template <typename>
-struct DistributionCaller;
-class MockHelpers;
-
-}  // namespace random_internal
 
 // -----------------------------------------------------------------------------
 // absl::BitGenRef
@@ -87,24 +63,18 @@
 //    }
 //
 class BitGenRef {
-  // SFINAE to detect whether the URBG type includes a member matching
-  // bool InvokeMock(key_id, args_tuple*, result*).
-  //
-  // These live inside BitGenRef so that they have friend access
-  // to MockingBitGen. (see similar methods in DistributionCaller).
   template <template <class...> class Trait, class AlwaysVoid, class... Args>
   struct detector : std::false_type {};
   template <template <class...> class Trait, class... Args>
   struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
       : std::true_type {};
 
-  template <class T>
-  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<FastTypeIdType>(), std::declval<void*>(),
-      std::declval<void*>()));
+  template <typename T>
+  using has_conversion_operator_t =
+      decltype(std::declval<T>().operator BitGenRef());
 
   template <typename T>
-  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
+  using HasConversionOperator = detector<has_conversion_operator_t, void, T>;
 
  public:
   BitGenRef(const BitGenRef&) = default;
@@ -112,23 +82,28 @@
   BitGenRef& operator=(const BitGenRef&) = default;
   BitGenRef& operator=(BitGenRef&&) = default;
 
-  template <
-      typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
-      typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
-                                  random_internal::is_urbg<URBG>::value &&
-                                  !HasInvokeMock<URBG>::value)>* = nullptr>
+  template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
+            typename absl::enable_if_t<
+                (!std::is_same<URBG, BitGenRef>::value &&
+                 !std::is_base_of<BitGenRef, URBG>::value &&
+                 !HasConversionOperator<URBG>::value &&
+                 random_internal::is_urbg<URBG>::value &&
+                 !RandomMockingAccess::HasInvokeMock<URBG>::value)>* = nullptr>
   BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
         mock_call_(NotAMock),
         generate_impl_fn_(ImplFn<URBG>) {}
 
   template <typename URBGRef, typename URBG = absl::remove_cvref_t<URBGRef>,
-            typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
-                                        random_internal::is_urbg<URBG>::value &&
-                                        HasInvokeMock<URBG>::value)>* = nullptr>
+            typename absl::enable_if_t<
+                (!std::is_same<URBG, BitGenRef>::value &&
+                 !std::is_base_of<BitGenRef, URBG>::value &&
+                 !HasConversionOperator<URBG>::value &&
+                 random_internal::is_urbg<URBG>::value &&
+                 RandomMockingAccess::HasInvokeMock<URBG>::value)>* = nullptr>
   BitGenRef(URBGRef&& gen ABSL_ATTRIBUTE_LIFETIME_BOUND)  // NOLINT
       : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
-        mock_call_(&MockCall<URBG>),
+        mock_call_(MockCall<URBG>),
         generate_impl_fn_(ImplFn<URBG>) {}
 
   using result_type = uint64_t;
@@ -157,10 +132,10 @@
 
   // Get a type-erased InvokeMock pointer.
   template <typename URBG>
-  static bool MockCall(uintptr_t gen_ptr, FastTypeIdType key_id, void* result,
-                       void* arg_tuple) {
-    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(key_id, result,
-                                                        arg_tuple);
+  static bool MockCall(uintptr_t gen_ptr, FastTypeIdType key_id,
+                       void* args_tuple, void* result) {
+    return RandomMockingAccess::InvokeMock(reinterpret_cast<URBG*>(gen_ptr),
+                                           key_id, args_tuple, result);
   }
   static bool NotAMock(uintptr_t, FastTypeIdType, void*, void*) {
     return false;
@@ -176,9 +151,7 @@
   mock_call_fn mock_call_;
   impl_fn generate_impl_fn_;
 
-  template <typename>
-  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
-  friend class ::absl::random_internal::MockHelpers;          // for InvokeMock
+  friend class ::absl::RandomMockingAccess;  // for InvokeMock
 };
 
 ABSL_NAMESPACE_END
diff --git a/absl/random/bit_gen_ref_test.cc b/absl/random/bit_gen_ref_test.cc
index d581352..d04ac3a 100644
--- a/absl/random/bit_gen_ref_test.cc
+++ b/absl/random/bit_gen_ref_test.cc
@@ -17,6 +17,7 @@
 
 #include <cstdint>
 #include <random>
+#include <type_traits>
 #include <vector>
 
 #include "gmock/gmock.h"
@@ -102,6 +103,48 @@
   absl::BitGenRef gen_ref(const_gen);
   EXPECT_EQ(FnTest(gen_ref), 42);  // Copy
 }
+
+struct MinStdRand {
+  // The URBG just returns 0.
+  using result_type = absl::BitGen::result_type;
+  static constexpr result_type(min)() { return (absl::BitGen::min)(); }
+  static constexpr result_type(max)() { return (absl::BitGen::max)(); }
+  result_type operator()() { return 0; }
+
+  // Implicit conversions allow passing MinStdRand to functions taking
+  // absl::BitGenRef as well as explicitly constructing an absl::BitGenRef from
+  // a MinStdRand.
+  operator absl::BitGenRef() const {
+    conversion_count++;
+    return absl::BitGenRef(minstd_gen);
+  }
+
+  std::minstd_rand minstd_gen;
+  mutable int conversion_count = 0;
+};
+
+TEST(BitGenRefTest, IsConvertibleTest) {
+  // Verify that MinStdRandBitGen is convertible to absl::BitGenRef.
+  EXPECT_TRUE((std::is_convertible<MinStdRand, absl::BitGenRef>::value));
+
+  // Explicit construction should trigger the conversion.
+  {
+    MinStdRand minstd;
+    absl::BitGenRef gen_ref(minstd);
+    EXPECT_EQ(minstd.conversion_count, 1);
+    (void)gen_ref;
+  }
+
+  // Calling a function that accepts absl::BitGenRef should trigger the
+  // conversion. This tests implicit conversion.
+  {
+    MinStdRand minstd;
+    auto result = FnTest(minstd);
+    EXPECT_EQ(minstd.conversion_count, 1);
+    EXPECT_GE(result, 1);
+  }
+}
+
 }  // namespace
 ABSL_NAMESPACE_END
 }  // namespace absl
diff --git a/absl/random/internal/BUILD.bazel b/absl/random/internal/BUILD.bazel
index c2f2c36..56377ed 100644
--- a/absl/random/internal/BUILD.bazel
+++ b/absl/random/internal/BUILD.bazel
@@ -116,6 +116,7 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         "//absl/base:config",
+        "//absl/meta:type_traits",
         "//absl/numeric:bits",
         "//absl/numeric:int128",
     ],
@@ -130,6 +131,7 @@
         "//absl/base:config",
         "//absl/base:fast_type_id",
         "//absl/meta:type_traits",
+        "//absl/random:mocking_access",
         "//absl/utility",
     ],
 )
@@ -592,7 +594,7 @@
     deps = [
         "//absl/base:config",
         "//absl/base:fast_type_id",
-        "//absl/types:optional",
+        "//absl/random:mocking_access",
     ],
 )
 
diff --git a/absl/random/internal/distribution_caller.h b/absl/random/internal/distribution_caller.h
index e84ec8c..d712bca 100644
--- a/absl/random/internal/distribution_caller.h
+++ b/absl/random/internal/distribution_caller.h
@@ -24,6 +24,7 @@
 #include "absl/base/config.h"
 #include "absl/base/fast_type_id.h"
 #include "absl/meta/type_traits.h"
+#include "absl/random/mocking_access.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
@@ -37,23 +38,8 @@
 struct DistributionCaller {
   static_assert(!std::is_pointer<URBG>::value,
                 "You must pass a reference, not a pointer.");
-  // SFINAE to detect whether the URBG type includes a member matching
-  // bool InvokeMock(key_id, args_tuple*, result*).
-  //
-  // These live inside BitGenRef so that they have friend access
-  // to MockingBitGen. (see similar methods in DistributionCaller).
-  template <template <class...> class Trait, class AlwaysVoid, class... Args>
-  struct detector : std::false_type {};
-  template <template <class...> class Trait, class... Args>
-  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
-      : std::true_type {};
 
-  template <class T>
-  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<FastTypeIdType>(), std::declval<void*>(),
-      std::declval<void*>()));
-
-  using HasInvokeMock = typename detector<invoke_mock_t, void, URBG>::type;
+  using RandomMockingAccess = ::absl::RandomMockingAccess;
 
   // Default implementation of distribution caller.
   template <typename DistrT, typename... Args>
@@ -74,7 +60,8 @@
 
     ArgTupleT arg_tuple(std::forward<Args>(args)...);
     ResultT result;
-    if (!urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {
+    if (!RandomMockingAccess::InvokeMock<URBG>(urbg, FastTypeId<KeyT>(),
+                                               &arg_tuple, &result)) {
       auto dist = absl::make_from_tuple<DistrT>(arg_tuple);
       result = dist(*urbg);
     }
@@ -84,8 +71,8 @@
   // Default implementation of distribution caller.
   template <typename DistrT, typename... Args>
   static typename DistrT::result_type Call(URBG* urbg, Args&&... args) {
-    return Impl<DistrT, Args...>(HasInvokeMock{}, urbg,
-                                 std::forward<Args>(args)...);
+    return Impl<DistrT, Args...>(RandomMockingAccess::HasInvokeMock<URBG>{},
+                                 urbg, std::forward<Args>(args)...);
   }
 };
 
diff --git a/absl/random/internal/mock_helpers.h b/absl/random/internal/mock_helpers.h
index 2d66a3b..b73b9cb 100644
--- a/absl/random/internal/mock_helpers.h
+++ b/absl/random/internal/mock_helpers.h
@@ -21,7 +21,7 @@
 
 #include "absl/base/config.h"
 #include "absl/base/fast_type_id.h"
-#include "absl/types/optional.h"
+#include "absl/random/mocking_access.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
@@ -50,6 +50,7 @@
 //
 class MockHelpers {
   using IdType = ::absl::FastTypeIdType;
+  using RandomMockingAccess = ::absl::RandomMockingAccess;
 
   // Given a key signature type used to index the mock, extract the components.
   // KeyT is expected to have the form:
@@ -64,39 +65,7 @@
     using arg_tuple_type = ArgTupleT;
   };
 
-  // Detector for InvokeMock.
-  template <class T>
-  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
-      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
-
-  // Empty implementation of InvokeMock.
-  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
-            typename... Args>
-  static std::optional<ReturnT> InvokeMockImpl(char, URBG*, Args&&...) {
-    return std::nullopt;
-  }
-
-  // Non-empty implementation of InvokeMock.
-  template <typename KeyT, typename ReturnT, typename ArgTupleT, typename URBG,
-            typename = invoke_mock_t<URBG>, typename... Args>
-  static std::optional<ReturnT> InvokeMockImpl(int, URBG* urbg,
-                                               Args&&... args) {
-    ArgTupleT arg_tuple(std::forward<Args>(args)...);
-    ReturnT result;
-    if (urbg->InvokeMock(FastTypeId<KeyT>(), &arg_tuple, &result)) {
-      return result;
-    }
-    return std::nullopt;
-  }
-
  public:
-  // InvokeMock is private; this provides access for some specialized use cases.
-  template <typename URBG>
-  static inline bool PrivateInvokeMock(URBG* urbg, IdType key_id,
-                                       void* args_tuple, void* result) {
-    return urbg->InvokeMock(key_id, args_tuple, result);
-  }
-
   // Invoke a mock for the KeyT (may or may not be a signature).
   //
   // KeyT is used to generate a typeid-based lookup key for the mock.
@@ -110,12 +79,16 @@
   template <typename KeyT, typename URBG, typename... Args>
   static auto MaybeInvokeMock(URBG* urbg, Args&&... args)
       -> std::optional<typename KeySignature<KeyT>::result_type> {
-    // Use function overloading to dispatch to the implementation since
-    // more modern patterns (e.g. require + constexpr) are not supported in all
-    // compiler configurations.
-    return InvokeMockImpl<KeyT, typename KeySignature<KeyT>::result_type,
-                          typename KeySignature<KeyT>::arg_tuple_type, URBG>(
-        0, urbg, std::forward<Args>(args)...);
+    if constexpr (RandomMockingAccess::HasInvokeMock<URBG>::value) {
+      typename KeySignature<KeyT>::arg_tuple_type arg_tuple(
+          std::forward<Args>(args)...);
+      typename KeySignature<KeyT>::result_type result;
+      if (RandomMockingAccess::InvokeMock(urbg, FastTypeId<KeyT>(), &arg_tuple,
+                                          &result)) {
+        return result;
+      }
+    }
+    return std::nullopt;
   }
 
   // Acquire a mock for the KeyT (may or may not be a signature), set up to use
diff --git a/absl/random/internal/traits.h b/absl/random/internal/traits.h
index f874a0f..d396329 100644
--- a/absl/random/internal/traits.h
+++ b/absl/random/internal/traits.h
@@ -20,6 +20,7 @@
 #include <type_traits>
 
 #include "absl/base/config.h"
+#include "absl/meta/type_traits.h"
 #include "absl/numeric/bits.h"
 #include "absl/numeric/int128.h"
 
@@ -27,6 +28,26 @@
 ABSL_NAMESPACE_BEGIN
 namespace random_internal {
 
+// is_urbg<URBG>
+//
+// Indicates whether a type URBG is a Uniform Random Bit Generator.
+template <typename URBG, typename = void, typename = void, typename = void>
+struct is_urbg : std::false_type {};
+
+template <typename URBG>
+struct is_urbg<
+    URBG,
+    absl::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype((URBG::min)())>::type>::value>,
+    absl::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype((URBG::max)())>::type>::value>,
+    absl::enable_if_t<std::is_same<
+        typename URBG::result_type,
+        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
+    : std::true_type {};
+
 // random_internal::is_widening_convertible<A, B>
 //
 // Returns whether a type A is widening-convertible to a type B.
diff --git a/absl/random/internal/traits_test.cc b/absl/random/internal/traits_test.cc
index 2164582..100fd9b 100644
--- a/absl/random/internal/traits_test.cc
+++ b/absl/random/internal/traits_test.cc
@@ -15,14 +15,19 @@
 #include "absl/random/internal/traits.h"
 
 #include <cstdint>
+#include <random>
 #include <type_traits>
 
 #include "gtest/gtest.h"
 
 namespace {
 
+using absl::random_internal::is_urbg;
 using absl::random_internal::is_widening_convertible;
 
+static_assert(is_urbg<std::minstd_rand>::value);
+static_assert(!is_urbg<uint64_t>::value);
+
 // CheckWideningConvertsToSelf<T1, T2, ...>()
 //
 // For each type T, checks:
diff --git a/absl/random/mocking_access.h b/absl/random/mocking_access.h
new file mode 100644
index 0000000..eb2f98b
--- /dev/null
+++ b/absl/random/mocking_access.h
@@ -0,0 +1,74 @@
+// Copyright 2019 The Abseil Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ABSL_RANDOM_MOCKING_ACCESS_H_
+#define ABSL_RANDOM_MOCKING_ACCESS_H_
+
+#include <type_traits>
+#include <utility>
+
+#include "absl/base/config.h"
+#include "absl/base/fast_type_id.h"
+#include "absl/meta/type_traits.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+// RandomMockingAccess must be a friend of any class which exposes an InvokeMock
+// method. All calls to InvokeMock should be made through RandomMockingAccess.
+//
+// Any URBG type which wants to participate in mocking should declare
+// RandomMockingAccess as a friend and have a protected or private method with
+// the signature:
+//
+// bool InvokeMock(absl::FastTypeIdType key_id, void* args_tuple, void* result)
+//
+// This method returns false when mocking is not enabled, otherwise it will
+// apply the mock.  Typically this will involve forwarding to an underlying
+// URBG such as absl::MockingBitGen by calling RandomMockingAccess::InvokeMock
+// after checking that RandomMockingAccess::HasInvokeMock<URBG> is true for the
+// underlying URBG type.
+class RandomMockingAccess {
+  template <template <class...> class Trait, class AlwaysVoid, class... Args>
+  struct detector : std::false_type {};
+  template <template <class...> class Trait, class... Args>
+  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
+      : std::true_type {};
+
+  using IdType = ::absl::FastTypeIdType;
+
+  // Detector for `bool InvokeMock(key_id, args_tuple*, result*)`
+  // Lives inside RandomMockingAccess so that it has friend access to private
+  // members of URBG types.
+  template <class T>
+  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
+      std::declval<IdType>(), std::declval<void*>(), std::declval<void*>()));
+
+ public:
+  // Returns true if the URBG type has an InvokeMock method.
+  template <typename T>
+  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;
+
+  // InvokeMock is private; calls to InvokeMock are proxied by MockingAccess.
+  template <typename URBG>
+  static inline bool InvokeMock(URBG* urbg, IdType key_id, void* args_tuple,
+                                void* result) {
+    return urbg->InvokeMock(key_id, args_tuple, result);
+  }
+};
+
+ABSL_NAMESPACE_END
+}  // namespace absl
+
+#endif  // ABSL_RANDOM_MOCKING_ACCESS_H_
diff --git a/absl/random/mocking_bit_gen.h b/absl/random/mocking_bit_gen.h
index 1680ff4..249e2d6 100644
--- a/absl/random/mocking_bit_gen.h
+++ b/absl/random/mocking_bit_gen.h
@@ -39,20 +39,13 @@
 #include "absl/container/flat_hash_map.h"
 #include "absl/meta/type_traits.h"
 #include "absl/random/internal/mock_helpers.h"
+#include "absl/random/mocking_access.h"
 #include "absl/random/random.h"
 #include "absl/utility/utility.h"
 
 namespace absl {
 ABSL_NAMESPACE_BEGIN
 
-class BitGenRef;
-
-namespace random_internal {
-template <typename>
-struct DistributionCaller;
-class MockHelpers;
-}  // namespace random_internal
-
 // MockingBitGen
 //
 // `absl::MockingBitGen` is a mock Uniform Random Bit Generator (URBG) class
@@ -224,11 +217,8 @@
   absl::flat_hash_map<FastTypeIdType, std::unique_ptr<FunctionHolder>> mocks_;
   absl::BitGen gen_;
 
-  template <typename>
-  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
-  friend class ::absl::BitGenRef;                             // for InvokeMock
-  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock,
-                                                      // InvokeMock
+  friend class ::absl::RandomMockingAccess;           // for InvokeMock
+  friend class ::absl::random_internal::MockHelpers;  // for RegisterMock
 };
 
 ABSL_NAMESPACE_END