diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2018-05-15 16:36:46 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2018-05-15 16:36:46 +0100 |
commit | 5a7960da41fec497eb4203d71215bcb1077207a9 (patch) | |
tree | 459507cfc4f9ff9bc0b70712e1db9fd0ce037432 /libstdc++-v3/include | |
parent | c3b61fdadd7ffc9ef5c613c2df0ff4edf83ad0fc (diff) | |
download | gcc-5a7960da41fec497eb4203d71215bcb1077207a9.zip gcc-5a7960da41fec497eb4203d71215bcb1077207a9.tar.gz gcc-5a7960da41fec497eb4203d71215bcb1077207a9.tar.bz2 |
PR libstdc++/85749 constrain seed sequences for random number engines
Constrain constructors and member functions of random number engines so
that functions taking seed sequences can only be called with types that
meet the seed sequence requirements.
PR libstdc++/85749
* include/bits/random.h (__detail::__is_seed_seq): New SFINAE helper.
(linear_congruential_engine, mersenne_twister_engine)
(subtract_with_carry_engine, discard_block_engine)
(independent_bits_engine, shuffle_order_engine): Use __is_seed_seq to
constrain function templates taking seed sequences.
* include/bits/random.tcc (linear_congruential_engine::seed(_Sseq&))
(mersenne_twister_engine::seed(_Sseq&))
(subtract_with_carry_engine::seed(_Sseq&)): Change return types to
match declarations.
* include/ext/random (simd_fast_mersenne_twister_engine): Use
__is_seed_seq to constrain function templates taking seed sequences.
* include/ext/random.tcc (simd_fast_mersenne_twister_engine::seed):
Change return type to match declaration.
* testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc:
New.
* testsuite/26_numerics/random/independent_bits_engine/cons/
seed_seq2.cc: New.
* testsuite/26_numerics/random/linear_congruential_engine/cons/
seed_seq2.cc: New.
* testsuite/26_numerics/random/mersenne_twister_engine/cons/
seed_seq2.cc: New.
* testsuite/26_numerics/random/pr60037-neg.cc: Adjust dg-error lineno.
* testsuite/26_numerics/random/shuffle_order_engine/cons/seed_seq2.cc:
New.
* testsuite/26_numerics/random/subtract_with_carry_engine/cons/
seed_seq2.cc: New.
* testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/
seed_seq2.cc: New.
From-SVN: r260263
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/bits/random.h | 78 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/random.tcc | 9 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/random | 13 | ||||
-rw-r--r-- | libstdc++-v3/include/ext/random.tcc | 3 |
4 files changed, 67 insertions, 36 deletions
diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index f812bbf..b76cfbb 100644 --- a/libstdc++-v3/include/bits/random.h +++ b/libstdc++-v3/include/bits/random.h @@ -185,6 +185,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Engine& _M_g; }; + template<typename _Sseq> + using __seed_seq_generate_t = decltype( + std::declval<_Sseq&>().generate(std::declval<uint_least32_t*>(), + std::declval<uint_least32_t*>())); + + // Detect whether _Sseq is a valid seed sequence for + // a random number engine _Engine with result type _Res. + template<typename _Sseq, typename _Engine, typename _Res, + typename _GenerateCheck = __seed_seq_generate_t<_Sseq>> + using __is_seed_seq = __and_< + __not_<is_same<__remove_cvref_t<_Sseq>, _Engine>>, + is_unsigned<typename _Sseq::result_type>, + __not_<is_convertible<_Sseq, _Res>> + >; + } // namespace __detail /** @@ -233,6 +248,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(__m == 0u || (__a < __m && __c < __m), "template argument substituting __m out of bounds"); + template<typename _Sseq> + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, linear_congruential_engine, _UIntType>::value>::type; + public: /** The type of the generated random value. */ typedef _UIntType result_type; @@ -262,9 +281,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @param __q the seed sequence. */ - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, linear_congruential_engine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit linear_congruential_engine(_Sseq& __q) { seed(__q); } @@ -286,7 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q the seed sequence. */ template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + _If_seed_seq<_Sseq> seed(_Sseq& __q); /** @@ -463,6 +480,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(__f <= (__detail::_Shift<_UIntType, __w>::__value - 1), "template argument substituting __f out of bound"); + template<typename _Sseq> + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, mersenne_twister_engine, _UIntType>::value>::type; + public: /** The type of the generated random value. */ typedef _UIntType result_type; @@ -494,9 +515,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @param __q the seed sequence. */ - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, mersenne_twister_engine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit mersenne_twister_engine(_Sseq& __q) { seed(__q); } @@ -505,7 +524,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION seed(result_type __sd = default_seed); template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + _If_seed_seq<_Sseq> seed(_Sseq& __q); /** @@ -658,6 +677,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, "template argument substituting __w out of bounds"); + template<typename _Sseq> + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, subtract_with_carry_engine, _UIntType>::value>::type; + public: /** The type of the generated random value. */ typedef _UIntType result_type; @@ -682,9 +705,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @param __q the seed sequence. */ - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, subtract_with_carry_engine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit subtract_with_carry_engine(_Sseq& __q) { seed(__q); } @@ -709,7 +730,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * % subtract_with_carry_engine random number generator. */ template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + _If_seed_seq<_Sseq> seed(_Sseq& __q); /** @@ -845,6 +866,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** The type of the generated random value. */ typedef typename _RandomNumberEngine::result_type result_type; + template<typename _Sseq> + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, discard_block_engine, result_type>::value>::type; + // parameter values static constexpr size_t block_size = __p; static constexpr size_t used_block = __r; @@ -892,10 +917,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @param __q A seed sequence. */ - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, discard_block_engine>::value - && !std::is_same<_Sseq, _RandomNumberEngine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit discard_block_engine(_Sseq& __q) : _M_b(__q), _M_n(0) @@ -929,7 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q A seed generator function. */ template<typename _Sseq> - void + _If_seed_seq<_Sseq> seed(_Sseq& __q) { _M_b.seed(__q); @@ -1063,6 +1085,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, "template argument substituting __w out of bounds"); + template<typename _Sseq> + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, independent_bits_engine, _UIntType>::value>::type; + public: /** The type of the generated random value. */ typedef _UIntType result_type; @@ -1110,10 +1136,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @param __q A seed sequence. */ - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, independent_bits_engine>::value - && !std::is_same<_Sseq, _RandomNumberEngine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit independent_bits_engine(_Sseq& __q) : _M_b(__q) @@ -1141,7 +1164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q A seed generator function. */ template<typename _Sseq> - void + _If_seed_seq<_Sseq> seed(_Sseq& __q) { _M_b.seed(__q); } @@ -1283,6 +1306,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /** The type of the generated random value. */ typedef typename _RandomNumberEngine::result_type result_type; + template<typename _Sseq> + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, shuffle_order_engine, result_type>::value>::type; + static constexpr size_t table_size = __k; /** @@ -1332,10 +1359,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * * @param __q A seed sequence. */ - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, shuffle_order_engine>::value - && !std::is_same<_Sseq, _RandomNumberEngine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit shuffle_order_engine(_Sseq& __q) : _M_b(__q) @@ -1369,7 +1393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q A seed generator function. */ template<typename _Sseq> - void + _If_seed_seq<_Sseq> seed(_Sseq& __q) { _M_b.seed(__q); diff --git a/libstdc++-v3/include/bits/random.tcc b/libstdc++-v3/include/bits/random.tcc index f398150..9ec2989 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -128,9 +128,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template<typename _UIntType, _UIntType __a, _UIntType __c, _UIntType __m> template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + auto linear_congruential_engine<_UIntType, __a, __c, __m>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { const _UIntType __k0 = __m == 0 ? std::numeric_limits<_UIntType>::digits : std::__lg(__m); @@ -346,10 +347,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _UIntType __b, size_t __t, _UIntType __c, size_t __l, _UIntType __f> template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + auto mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { const _UIntType __upper_mask = (~_UIntType()) << __r; const size_t __k = (__w + 31) / 32; @@ -564,9 +566,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _UIntType, size_t __w, size_t __s, size_t __r> template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + auto subtract_with_carry_engine<_UIntType, __w, __s, __r>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { const size_t __k = (__w + 31) / 32; uint_least32_t __arr[__r * __k]; diff --git a/libstdc++-v3/include/ext/random b/libstdc++-v3/include/ext/random index 0a98b35..7e93186 100644 --- a/libstdc++-v3/include/ext/random +++ b/libstdc++-v3/include/ext/random @@ -85,6 +85,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(16 % sizeof(_UIntType) == 0, "UIntType size must divide 16"); + template<typename _Sseq> + using _If_seed_seq + = typename std::enable_if<std::__detail::__is_seed_seq< + _Sseq, simd_fast_mersenne_twister_engine, result_type>::value + >::type; + public: static constexpr size_t state_size = _M_nstate * (16 / sizeof(result_type)); @@ -95,10 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION simd_fast_mersenne_twister_engine(result_type __sd = default_seed) { seed(__sd); } - template<typename _Sseq, typename = typename - std::enable_if<!std::is_same<_Sseq, - simd_fast_mersenne_twister_engine>::value> - ::type> + template<typename _Sseq, typename = _If_seed_seq<_Sseq>> explicit simd_fast_mersenne_twister_engine(_Sseq& __q) { seed(__q); } @@ -107,7 +110,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION seed(result_type __sd = default_seed); template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + _If_seed_seq<_Sseq> seed(_Sseq& __q); static constexpr result_type diff --git a/libstdc++-v3/include/ext/random.tcc b/libstdc++-v3/include/ext/random.tcc index 07857dd..d845f25 100644 --- a/libstdc++-v3/include/ext/random.tcc +++ b/libstdc++-v3/include/ext/random.tcc @@ -85,13 +85,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION uint32_t __parity1, uint32_t __parity2, uint32_t __parity3, uint32_t __parity4> template<typename _Sseq> - typename std::enable_if<std::is_class<_Sseq>::value>::type + auto simd_fast_mersenne_twister_engine<_UIntType, __m, __pos1, __sl1, __sl2, __sr1, __sr2, __msk1, __msk2, __msk3, __msk4, __parity1, __parity2, __parity3, __parity4>:: seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> { size_t __lag; |