From: Jonathan Wakely Date: Tue, 15 May 2018 15:36:46 +0000 (+0100) Subject: PR libstdc++/85749 constrain seed sequences for random number engines X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5a7960da41fec497eb4203d71215bcb1077207a9;p=gcc.git 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 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 03d4e51e85c..8359f4f5335 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,35 @@ 2018-05-15 Jonathan Wakely + 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. + PR libstdc++/83891 * include/bits/fs_path.h (path::is_absolute()): Use same definition for all operating systems. diff --git a/libstdc++-v3/include/bits/random.h b/libstdc++-v3/include/bits/random.h index f812bbf18b1..b76cfbb558e 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 + using __seed_seq_generate_t = decltype( + std::declval<_Sseq&>().generate(std::declval(), + std::declval())); + + // Detect whether _Sseq is a valid seed sequence for + // a random number engine _Engine with result type _Res. + template> + using __is_seed_seq = __and_< + __not_, _Engine>>, + is_unsigned, + __not_> + >; + } // 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 + 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::value> - ::type> + template> explicit linear_congruential_engine(_Sseq& __q) { seed(__q); } @@ -286,7 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q the seed sequence. */ template - typename std::enable_if::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 + 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::value> - ::type> + template> explicit mersenne_twister_engine(_Sseq& __q) { seed(__q); } @@ -505,7 +524,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION seed(result_type __sd = default_seed); template - typename std::enable_if::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 + 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::value> - ::type> + template> 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 std::enable_if::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 + 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::value - && !std::is_same<_Sseq, _RandomNumberEngine>::value> - ::type> + template> 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 - 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 + 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::value - && !std::is_same<_Sseq, _RandomNumberEngine>::value> - ::type> + template> explicit independent_bits_engine(_Sseq& __q) : _M_b(__q) @@ -1141,7 +1164,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q A seed generator function. */ template - 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 + 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::value - && !std::is_same<_Sseq, _RandomNumberEngine>::value> - ::type> + template> explicit shuffle_order_engine(_Sseq& __q) : _M_b(__q) @@ -1369,7 +1393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @param __q A seed generator function. */ template - 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 f398150d416..9ec29895d27 100644 --- a/libstdc++-v3/include/bits/random.tcc +++ b/libstdc++-v3/include/bits/random.tcc @@ -128,9 +128,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ template template - typename std::enable_if::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 std::enable_if::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 template - typename std::enable_if::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 0a98b350925..7e931865af3 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 + using _If_seed_seq + = typename std::enable_if::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::value> - ::type> + template> 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 std::enable_if::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 07857dd6c82..d845f253ab7 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 std::enable_if::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; diff --git a/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc new file mode 100644 index 00000000000..0e44ffff2eb --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/discard_block_engine/cons/seed_seq2.cc @@ -0,0 +1,87 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = std::discard_block_engine + < + std::subtract_with_carry_engine, + 389, 24 + >; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc new file mode 100644 index 00000000000..4fad65121d6 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/independent_bits_engine/cons/seed_seq2.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = std::independent_bits_engine + < + std::subtract_with_carry_engine, + 48, + uint_fast64_t + >; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc new file mode 100644 index 00000000000..3330b47ea70 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/linear_congruential_engine/cons/seed_seq2.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = std::linear_congruential_engine; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc new file mode 100644 index 00000000000..d900bc378d8 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/mersenne_twister_engine/cons/seed_seq2.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = std::mersenne_twister_engine< + unsigned long, 32, 624, 397, 31, + 0x9908b0dful, 11, + 0xfffffffful, 7, + 0x9d2c5680ul, 15, + 0xefc60000ul, 18, 1812433253ul>; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc index 13c052daef8..1ead99cffc4 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/pr60037-neg.cc @@ -11,4 +11,4 @@ auto x = std::generate_canonical. + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = std::shuffle_order_engine + < + std::linear_congruential_engine, + 256 + >; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc new file mode 100644 index 00000000000..e4a13a72b45 --- /dev/null +++ b/libstdc++-v3/testsuite/26_numerics/random/subtract_with_carry_engine/cons/seed_seq2.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = std::subtract_with_carry_engine; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc b/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc new file mode 100644 index 00000000000..325e27517b1 --- /dev/null +++ b/libstdc++-v3/testsuite/ext/random/simd_fast_mersenne_twister_engine/cons/seed_seq2.cc @@ -0,0 +1,90 @@ +// Copyright (C) 2018 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 +// . + +// { dg-do run { target c++11 } } +// { dg-require-cstdint "" } +// { dg-require-little-endian "" } + +#include +#include + +template +struct seed_seq +{ + using result_type = unsigned; + + seed_seq() { } + + template + seed_seq(std::initializer_list) { } + + template + seed_seq(InputIterator, InputIterator) { } + + template + void generate(RandomAccessIterator first, RandomAccessIterator last) + { + called = true; + if (first != last) + *first = 42; + } + + size_t size() const { called = true; return 1; } + + template + void param(OutputIterator dest) const { called = true; dest = 42; } + + // Prevents this type being considered as a seed sequence when + // T is convertible to the engine's result_type: + operator T() const noexcept { return T(); } + + bool called = false; +}; + +using engine_type + = __gnu_cxx::simd_fast_mersenne_twister_engine< + uint32_t, 607, 2, + 15, 3, 13, 3, + 0xfdff37ffU, 0xef7f3f7dU, + 0xff777b7dU, 0x7ff7fb2fU, + 0x00000001U, 0x00000000U, + 0x00000000U, 0x5986f054U>; + +void +test01() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( ! seed.called ); +} + +void +test02() +{ + seed_seq seed; + engine_type x(seed); + VERIFY( seed.called ); + + static_assert(!std::is_constructible&>(), + "Cannot construct from a const seed_seq"); +} + +int main() +{ + test01(); + test02(); +}