[libcxx] adds concept `std::uniform_random_bit_generator`
Implements parts of:
- P0898R3 Standard Library Concepts
- P1754 Rename concepts to standard_case for C++20, while we still can
Differential Revision: https://reviews.llvm.org/D96577
GitOrigin-RevId: 9f4f6ac94bfcb474fa71dab40f1dbee6ee57398f
diff --git a/include/concepts b/include/concepts
index 478b865..dac6b69 100644
--- a/include/concepts
+++ b/include/concepts
@@ -228,7 +228,7 @@
template<class _Fn, class... _Args>
concept regular_invocable = invocable<_Fn, _Args...>;
-#endif //_LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
+#endif // _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
_LIBCPP_END_NAMESPACE_STD
diff --git a/include/random b/include/random
index 6e0d2ec..1cbe9b5 100644
--- a/include/random
+++ b/include/random
@@ -17,6 +17,9 @@
namespace std
{
+// [rand.req.urng], uniform random bit generator requirements
+template<class G>
+concept uniform_random_bit_generator = see below; // C++20
// Engines
@@ -1678,6 +1681,7 @@
#include <cstddef>
#include <cstdint>
#include <cmath>
+#include <concepts>
#include <type_traits>
#include <initializer_list>
#include <limits>
@@ -1697,6 +1701,20 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+#if _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
+
+// [rand.req.urng]
+template<class _Gen>
+concept uniform_random_bit_generator =
+ invocable<_Gen&> && unsigned_integral<invoke_result_t<_Gen&>> &&
+ requires {
+ { _Gen::min() } -> same_as<invoke_result_t<_Gen&>>;
+ { _Gen::max() } -> same_as<invoke_result_t<_Gen&>>;
+ requires bool_constant<(_Gen::min() < _Gen::max())>::value;
+ };
+
+#endif // _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L
+
// __is_seed_sequence
template <class _Sseq, class _Engine>
diff --git a/test/std/concepts/lang/arithmetic.pass.cpp b/test/std/concepts/lang/arithmetic.pass.cpp
index 7835b1c..9b7b75b 100644
--- a/test/std/concepts/lang/arithmetic.pass.cpp
+++ b/test/std/concepts/lang/arithmetic.pass.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17
+// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// template<class T>
diff --git a/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp b/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp
deleted file mode 100644
index 1f764da..0000000
--- a/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp
+++ /dev/null
@@ -1,13 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-int main(int, char**)
-{
-
- return 0;
-}
diff --git a/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp b/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp
new file mode 100644
index 0000000..c212f9e
--- /dev/null
+++ b/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp
@@ -0,0 +1,143 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// template<class T>
+// concept uniform_random_bit_generator = // see below
+
+#include <random>
+
+static_assert(std::uniform_random_bit_generator<
+ std::linear_congruential_engine<unsigned int, 0U, 1U, 2U> >);
+
+#ifndef _LIBCPP_HAS_NO_INT128
+static_assert(std::uniform_random_bit_generator<
+ std::subtract_with_carry_engine<__uint128_t, 1U, 2U, 3U> >);
+#endif
+
+// Not invocable
+static_assert(!std::uniform_random_bit_generator<void>);
+static_assert(!std::uniform_random_bit_generator<int>);
+static_assert(!std::uniform_random_bit_generator<int[10]>);
+static_assert(!std::uniform_random_bit_generator<int*>);
+static_assert(!std::uniform_random_bit_generator<const int*>);
+static_assert(!std::uniform_random_bit_generator<volatile int*>);
+static_assert(!std::uniform_random_bit_generator<const volatile int*>);
+static_assert(!std::uniform_random_bit_generator<int&>);
+static_assert(!std::uniform_random_bit_generator<const int&>);
+static_assert(!std::uniform_random_bit_generator<volatile int&>);
+static_assert(!std::uniform_random_bit_generator<const volatile int&>);
+static_assert(!std::uniform_random_bit_generator<int&&>);
+static_assert(!std::uniform_random_bit_generator<const int&&>);
+static_assert(!std::uniform_random_bit_generator<volatile int&&>);
+static_assert(!std::uniform_random_bit_generator<const volatile int&&>);
+
+struct Empty {};
+static_assert(!std::uniform_random_bit_generator<Empty>);
+
+namespace WrongReturnType {
+using FunctionPointer = void (*)();
+static_assert(!std::uniform_random_bit_generator<FunctionPointer>);
+
+using FunctionReference = int (&)();
+static_assert(!std::uniform_random_bit_generator<FunctionReference>);
+
+struct FunctionObject {
+ unsigned long* operator()();
+};
+static_assert(!std::uniform_random_bit_generator<FunctionObject>);
+static_assert(!std::uniform_random_bit_generator<unsigned int Empty::*>);
+static_assert(!std::uniform_random_bit_generator<unsigned short (Empty::*)()>);
+} // namespace WrongReturnType
+
+namespace NoMinOrMax {
+using FunctionPointer = unsigned int (*)();
+static_assert(!std::uniform_random_bit_generator<FunctionPointer>);
+
+using FunctionReference = unsigned long long (&)();
+static_assert(!std::uniform_random_bit_generator<FunctionReference>);
+
+struct FunctionObject {
+ unsigned char operator()();
+};
+static_assert(!std::uniform_random_bit_generator<FunctionObject>);
+} // namespace NoMinOrMax
+
+namespace OnlyMinIsRight {
+struct NoMax {
+ unsigned char operator()();
+
+ static unsigned char min();
+};
+static_assert(!std::uniform_random_bit_generator<NoMax>);
+
+struct MaxHasWrongReturnType {
+ unsigned char operator()();
+
+ static unsigned char min();
+ static unsigned int max();
+};
+
+static_assert(!std::uniform_random_bit_generator<MaxHasWrongReturnType>);
+} // namespace OnlyMinIsRight
+
+namespace OnlyMaxIsRight {
+struct NoMin {
+ unsigned char operator()();
+
+ static unsigned char max();
+};
+static_assert(!std::uniform_random_bit_generator<NoMin>);
+
+struct MinHasWrongReturnType {
+ unsigned char operator()();
+
+ static unsigned int min();
+ static unsigned char max();
+};
+
+static_assert(!std::uniform_random_bit_generator<MinHasWrongReturnType>);
+} // namespace OnlyMaxIsRight
+
+namespace MinNotLessMax {
+struct NotConstexpr {
+ unsigned char operator()();
+
+ static unsigned char min();
+ static unsigned char max();
+};
+static_assert(!std::uniform_random_bit_generator<NotConstexpr>);
+
+struct MinEqualsMax {
+ unsigned char operator()();
+
+ static constexpr unsigned char min() { return 0; }
+ static constexpr unsigned char max() { return 0; }
+};
+static_assert(!std::uniform_random_bit_generator<MinEqualsMax>);
+
+struct MaxLessThanMin {
+ unsigned char operator()();
+
+ static constexpr unsigned char min() { return 1; }
+ static constexpr unsigned char max() { return 0; }
+};
+static_assert(!std::uniform_random_bit_generator<MaxLessThanMin>);
+} // namespace MinNotLessMax
+
+struct Works {
+ unsigned char operator()();
+
+ static constexpr unsigned char min() { return 0; }
+ static constexpr unsigned char max() { return 1; }
+};
+static_assert(std::uniform_random_bit_generator<Works>);
+
+int main(int, char**) { return 0; }