* include/bits/random.h (uniform_random_bit_generator): Define for C++20. * testsuite/26_numerics/random/concept.cc: New test. * testsuite/26_numerics/random/pr60037-neg.cc: Adjust dg-error line.
This is the last piece of P0898R3, "C++20 concepts library", although other proposals added more concepty things to <iterator> and other headers (patch incoming for that). Tested powerpc64le-linux, committed to trunk.
commit d8fc3b4d03aeceef9dab968395dfc346db754b27 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Oct 24 09:10:25 2019 +0100 Define std::uniform_random_bit_generator concept for C++20 * include/bits/random.h (uniform_random_bit_generator): Define for C++20. * testsuite/26_numerics/random/concept.cc: New test. * testsuite/26_numerics/random/pr60037-neg.cc: Adjust dg-error line. diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index e63dbcf5a25..270097e07e6 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -33,6 +33,9 @@ #include <vector> #include <bits/uniform_int_dist.h> +#if __cplusplus > 201703L +# include <concepts> +#endif namespace std _GLIBCXX_VISIBILITY(default) { @@ -48,6 +51,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ +#ifdef __cpp_lib_concepts + /// Requirements for a uniform random bit generator. + template<typename _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&>>; + }; +#endif + /** * @brief A function template for converting the output of a (integral) * uniform random number generator to a floatng point result in the range diff --git a/libstdc++-v3/testsuite/26_numerics/random/concept.cc b/libstdc++-v3/testsuite/26_numerics/random/concept.cc new file mode 100644 index 00000000000..1794ad05419 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/concept.cc @@ -0,0 +1,221 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } +// { dg-require-cstdint "" } + +#include <random> + +static_assert( std::uniform_random_bit_generator<std::default_random_engine> ); +static_assert( std::uniform_random_bit_generator<std::minstd_rand0> ); +static_assert( std::uniform_random_bit_generator<std::mt19937> ); + +struct G1 +{ + unsigned char operator()(); + static constexpr unsigned char min() { return 0; } + static constexpr unsigned char max() { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G1> ); + +struct G2 +{ + unsigned operator()(); + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return -1U; } +}; + +static_assert( std::uniform_random_bit_generator<G2> ); + +struct G3 +{ + unsigned long long operator()(); + static constexpr unsigned long long min() { return 0; } + static constexpr unsigned long long max() { return -1ULL; } +}; + +static_assert( std::uniform_random_bit_generator<G3> ); + +struct G4 +{ + unsigned operator()(int = 0, int = 0); // extra params, with default args + static constexpr unsigned min(long = 0) { return 0; } + static constexpr unsigned max(void* = nullptr) { return -1U; } +}; + +static_assert( std::uniform_random_bit_generator<G4> ); + +struct G5 +{ + unsigned operator()() &; // ref-qualifier + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G5> ); + +struct G6 +{ + unsigned operator()() const; // cv-qualifier + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G6> ); + +struct G7 +{ + unsigned operator()() volatile; // cv-qualifier + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G7> ); + +struct G8 +{ + unsigned operator()() const volatile; // cv-qualifiers + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G8> ); + +struct G9 +{ + unsigned operator()() const volatile; // cv-qualifiers + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G9> ); + +struct G10 +{ + unsigned operator()() const volatile & noexcept; // cv/ref/noexcept + static constexpr unsigned min() noexcept { return 0; } + static constexpr unsigned max() noexcept { return 10; } +}; + +static_assert( std::uniform_random_bit_generator<G10> ); + +// Negative tests. + +static_assert( ! std::uniform_random_bit_generator<void> ); +static_assert( ! std::uniform_random_bit_generator<int> ); +static_assert( ! std::uniform_random_bit_generator<unsigned(*)()> ); + +struct N1 +{ + unsigned operator()(); + constexpr unsigned min() { return 0; } // non-static + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N1> ); + +struct N2 +{ + unsigned operator()(); + static constexpr unsigned min() { return 0; } + constexpr unsigned max() { return 1; } // non-static +}; + +static_assert( ! std::uniform_random_bit_generator<N2> ); + +struct N3 +{ + unsigned operator()(); + // no N3::min() + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N3> ); + +struct N4 +{ + unsigned operator()(); + static constexpr unsigned min() { return 0; } + // no N4::max() +}; + +static_assert( ! std::uniform_random_bit_generator<N4> ); + +struct N5 +{ + // no operator() + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N5> ); + +struct N6 +{ + int operator()(); // returns signed integral + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N6> ); + +struct N7 +{ + unsigned operator()(); + static constexpr unsigned long min() { return 0; } // different return type + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N7> ); + +struct N8 +{ + unsigned operator()(); + static constexpr unsigned min() { return 0; } + static constexpr unsigned long max() { return 1; } // different return type +}; + +static_assert( ! std::uniform_random_bit_generator<N8> ); + +struct N9 +{ + unsigned operator()(); + static constexpr unsigned long min() { return 0; } // different return type + static constexpr unsigned long max() { return 1; } // different return type +}; + +static_assert( ! std::uniform_random_bit_generator<N9> ); + +struct N10 +{ + unsigned operator()() &&; // ref-qualifier + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N10> ); + +struct N11 +{ + unsigned operator()() const &&; // ref-qualifier + static constexpr unsigned min() { return 0; } + static constexpr unsigned max() { return 1; } +}; + +static_assert( ! std::uniform_random_bit_generator<N11> ); diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc index f365337e789..9f7b0cec565 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc @@ -10,6 +10,6 @@ std::__detail::_Adaptor<std::mt19937, unsigned long> aurng(urng); auto x = std::generate_canonical<std::size_t, std::numeric_limits<std::size_t>::digits>(urng); -// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 156 } +// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 171 } // { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3320 }