/* @file engine_concept.hpp */ #pragma once #include #include namespace std { #ifdef __clang__ # if __clang_major__ <= 11 template < class T > concept integral = std::is_integral_v; template < class T > concept signed_integral = std::integral && std::is_signed_v; template < class T > concept unsigned_integral = std::integral && !std::signed_integral; template< class F, class... Args > concept invocable = requires(F&& f, Args&&... args) { std::invoke(std::forward(f), std::forward(args)...); /* not required to be equality-preserving */ }; template< typename G > concept uniform_random_bit_generator = std::invocable && std::unsigned_integral> && requires { { G::min() } -> std::same_as>; { G::max() } -> std::same_as>; requires std::bool_constant<(G::min() < G::max())>::value; }; # endif #else /* uniform_random_bit_generator provided by gcc 12.3.2 */ /* uniform_random_bit_generator provided by clang 16 */ #endif } /*namespace std*/ namespace xo { namespace rng { /* an engine generates psuedo-random bits. * given * RngEngine eng = ...; * * RngEngine::result_type x = eng(); * * puts random bits into x. */ template concept engine_concept = requires(RngEngine engine, typename RngEngine::result_type r) { /* note: the first 4 requirements characterize UniformRandomBitGenerator */ typename RngEngine::result_type; { RngEngine(r) }; { engine.min() } -> std::same_as; { engine.max() } -> std::same_as; /* must return value in closed interval [.min(), .max()] */ { engine() } -> std::same_as; { engine.seed() }; { engine.seed(r) }; { engine == engine }; { engine != engine }; } #ifdef __clang__ // std::copyable apparently not available in clang11 ? #else && std::copyable #endif && std::uniform_random_bit_generator; } /*namespace rng*/ } /*namespace xo*/ /* end engine_concept.hpp */