2018-05-15 Jonathan Wakely <jwakely@redhat.com>
+ 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.
_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
/**
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;
*
* @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); }
* @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);
/**
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;
*
* @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); }
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_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;
*
* @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); }
* % 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);
/**
/** 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;
*
* @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)
* @param __q A seed generator function.
*/
template<typename _Sseq>
- void
+ _If_seed_seq<_Sseq>
seed(_Sseq& __q)
{
_M_b.seed(__q);
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;
*
* @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)
* @param __q A seed generator function.
*/
template<typename _Sseq>
- void
+ _If_seed_seq<_Sseq>
seed(_Sseq& __q)
{ _M_b.seed(__q); }
/** 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;
/**
*
* @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)
* @param __q A seed generator function.
*/
template<typename _Sseq>
- void
+ _If_seed_seq<_Sseq>
seed(_Sseq& __q)
{
_M_b.seed(__q);
*/
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);
_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;
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];
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));
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); }
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
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;
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<unsigned long, 24, 10, 24>,
+ 389, 24
+ >;
+
+void
+test01()
+{
+ seed_seq<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<uint_fast64_t, 48, 5, 12>,
+ 48,
+ uint_fast64_t
+ >;
+
+void
+test01()
+{
+ seed_seq<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<unsigned, 48271, 0, 2147483647>;
+
+void
+test01()
+{
+ seed_seq<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}
// { 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 *-*-* } 3317 }
+// { dg-error "static assertion failed: template argument must be a floating point type" "" { target *-*-* } 3320 }
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<uint_fast32_t,16807UL, 0UL, 2147483647UL>,
+ 256
+ >;
+
+void
+test01()
+{
+ seed_seq<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+
+#include <random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<unsigned long, 24, 10, 24>;
+
+void
+test01()
+{
+ seed_seq<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}
--- /dev/null
+// 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
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do run { target c++11 } }
+// { dg-require-cstdint "" }
+// { dg-require-little-endian "" }
+
+#include <ext/random>
+#include <testsuite_hooks.h>
+
+template<typename T>
+struct seed_seq
+{
+ using result_type = unsigned;
+
+ seed_seq() { }
+
+ template<class U>
+ seed_seq(std::initializer_list<U>) { }
+
+ template<class InputIterator>
+ seed_seq(InputIterator, InputIterator) { }
+
+ template<class RandomAccessIterator>
+ void generate(RandomAccessIterator first, RandomAccessIterator last)
+ {
+ called = true;
+ if (first != last)
+ *first = 42;
+ }
+
+ size_t size() const { called = true; return 1; }
+
+ template<class OutputIterator>
+ 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<unsigned> seed;
+ engine_type x(seed);
+ VERIFY( ! seed.called );
+}
+
+void
+test02()
+{
+ seed_seq<void*> seed;
+ engine_type x(seed);
+ VERIFY( seed.called );
+
+ static_assert(!std::is_constructible<engine_type, const seed_seq<void>&>(),
+ "Cannot construct from a const seed_seq");
+}
+
+int main()
+{
+ test01();
+ test02();
+}