diff --git a/libcxx/include/concepts b/libcxx/include/concepts --- a/libcxx/include/concepts +++ b/libcxx/include/concepts @@ -228,7 +228,7 @@ template 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/libcxx/include/random b/libcxx/include/random --- a/libcxx/include/random +++ b/libcxx/include/random @@ -17,6 +17,9 @@ namespace std { +// [rand.req.urng], uniform random bit generator requirements +template +concept uniform_random_bit_generator = see below; // C++20 // Engines @@ -1678,6 +1681,7 @@ #include #include #include +#include #include #include #include @@ -1697,6 +1701,20 @@ _LIBCPP_BEGIN_NAMESPACE_STD +#if _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L + +// [rand.req.urng] +template +concept uniform_random_bit_generator = + invocable<_Gen&> && unsigned_integral> && + requires { + { _Gen::min() } -> same_as>; + { _Gen::max() } -> same_as>; + requires bool_constant<(_Gen::min() < _Gen::max())>::value; + }; + +#endif // _LIBCPP_STD_VER > 17 && defined(__cpp_concepts) && __cpp_concepts >= 201811L + // __is_seed_sequence template diff --git a/libcxx/test/std/concepts/lang/arithmetic.pass.cpp b/libcxx/test/std/concepts/lang/arithmetic.pass.cpp --- a/libcxx/test/std/concepts/lang/arithmetic.pass.cpp +++ b/libcxx/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 diff --git a/libcxx/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp b/libcxx/test/std/numerics/rand/rand.req/rand.req.urng/nothing_to_do.pass.cpp deleted file mode 100644 --- a/libcxx/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/libcxx/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp b/libcxx/test/std/numerics/rand/rand.req/rand.req.urng/uniform_random_bit_generator.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/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 +// concept uniform_random_bit_generator = // see below + +#include + +static_assert(std::uniform_random_bit_generator< + std::linear_congruential_engine >); + +#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); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); + +struct Empty {}; +static_assert(!std::uniform_random_bit_generator); + +namespace WrongReturnType { +using FunctionPointer = void (*)(); +static_assert(!std::uniform_random_bit_generator); + +using FunctionReference = int (&)(); +static_assert(!std::uniform_random_bit_generator); + +struct FunctionObject { + unsigned long* operator()(); +}; +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +static_assert(!std::uniform_random_bit_generator); +} // namespace WrongReturnType + +namespace NoMinOrMax { +using FunctionPointer = unsigned int (*)(); +static_assert(!std::uniform_random_bit_generator); + +using FunctionReference = unsigned long long (&)(); +static_assert(!std::uniform_random_bit_generator); + +struct FunctionObject { + unsigned char operator()(); +}; +static_assert(!std::uniform_random_bit_generator); +} // namespace NoMinOrMax + +namespace OnlyMinIsRight { +struct NoMax { + unsigned char operator()(); + + static unsigned char min(); +}; +static_assert(!std::uniform_random_bit_generator); + +struct MaxHasWrongReturnType { + unsigned char operator()(); + + static unsigned char min(); + static unsigned int max(); +}; + +static_assert(!std::uniform_random_bit_generator); +} // namespace OnlyMinIsRight + +namespace OnlyMaxIsRight { +struct NoMin { + unsigned char operator()(); + + static unsigned char max(); +}; +static_assert(!std::uniform_random_bit_generator); + +struct MinHasWrongReturnType { + unsigned char operator()(); + + static unsigned int min(); + static unsigned char max(); +}; + +static_assert(!std::uniform_random_bit_generator); +} // namespace OnlyMaxIsRight + +namespace MinNotLessMax { +struct NotConstexpr { + unsigned char operator()(); + + static unsigned char min(); + static unsigned char max(); +}; +static_assert(!std::uniform_random_bit_generator); + +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); + +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); +} // 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); + +int main(int, char**) { return 0; }