[libc++] Fix LWG3422 "Issues of seed_seq's constructors"

https://cplusplus.github.io/LWG/issue3422

Also add a static_assert to check the "Mandates:" on the
iterator-pair constructor. Oddly, the `InputIterator` parameter
itself is merely preconditioned, not constrained, to satisfy the
input iterator requirements.

Also drive-by rename `init` to `__init`.

Differential Revision: https://reviews.llvm.org/D117962
This commit is contained in:
Arthur O'Dwyer 2022-01-22 15:13:13 -05:00
parent 6693c562f9
commit 8b29b84c99
5 changed files with 93 additions and 15 deletions

View File

@ -108,7 +108,7 @@
`3361 <https://wg21.link/LWG3361>`__,"``safe_range<SomeRange&>`` case","October 2021","","","|ranges|"
`3392 <https://wg21.link/LWG3392>`__,"``ranges::distance()`` cannot be used on a move-only iterator with a sized sentinel","October 2021","","","|ranges|"
`3407 <https://wg21.link/LWG3407>`__,"Some problems with the wording changes of P1739R4","October 2021","","","|ranges|"
`3422 <https://wg21.link/LWG3422>`__,"Issues of ``seed_seq``'s constructors","October 2021","",""
`3422 <https://wg21.link/LWG3422>`__,"Issues of ``seed_seq``'s constructors","October 2021","|Complete|","14.0"
`3470 <https://wg21.link/LWG3470>`__,"``convertible-to-non-slicing`` seems to reject valid case","October 2021","","","|ranges|"
`3480 <https://wg21.link/LWG3480>`__,"``directory_iterator`` and ``recursive_directory_iterator`` are not C++20 ranges","October 2021","|Complete|","14.0","|ranges|"
`3498 <https://wg21.link/LWG3498>`__,"Inconsistent ``noexcept``-specifiers for ``basic_syncbuf``","October 2021","",""

Can't render this file because it has a wrong number of fields in line 2.

View File

@ -31,25 +31,24 @@ public:
// types
typedef uint32_t result_type;
private:
vector<result_type> __v_;
template<class _InputIterator>
void init(_InputIterator __first, _InputIterator __last);
public:
// constructors
_LIBCPP_INLINE_VISIBILITY
seed_seq() _NOEXCEPT {}
#ifndef _LIBCPP_CXX03_LANG
template<class _Tp>
_LIBCPP_INLINE_VISIBILITY
seed_seq(initializer_list<_Tp> __il) {init(__il.begin(), __il.end());}
template<class _Tp, __enable_if_t<is_integral<_Tp>::value>* = nullptr>
_LIBCPP_INLINE_VISIBILITY
seed_seq(initializer_list<_Tp> __il) {
__init(__il.begin(), __il.end());
}
#endif // _LIBCPP_CXX03_LANG
template<class _InputIterator>
_LIBCPP_INLINE_VISIBILITY
seed_seq(_InputIterator __first, _InputIterator __last)
{init(__first, __last);}
_LIBCPP_INLINE_VISIBILITY
seed_seq(_InputIterator __first, _InputIterator __last) {
static_assert(is_integral<typename iterator_traits<_InputIterator>::value_type>::value,
"Mandates: iterator_traits<InputIterator>::value_type is an integer type");
__init(__first, __last);
}
// generating functions
template<class _RandomAccessIterator>
@ -68,11 +67,17 @@ public:
_LIBCPP_INLINE_VISIBILITY
static result_type _Tp(result_type __x) {return __x ^ (__x >> 27);}
private:
template<class _InputIterator>
void __init(_InputIterator __first, _InputIterator __last);
vector<result_type> __v_;
};
template<class _InputIterator>
void
seed_seq::init(_InputIterator __first, _InputIterator __last)
seed_seq::__init(_InputIterator __first, _InputIterator __last)
{
for (_InputIterator __s = __first; __s != __last; ++__s)
__v_.push_back(*__s & 0xFFFFFFFF);

View File

@ -19,8 +19,11 @@
int main(int, char**)
{
ASSERT_NOEXCEPT(std::seed_seq());
{
std::seed_seq s;
assert(s.size() == 0);
}
return 0;
}

View File

@ -18,11 +18,13 @@
#include "test_macros.h"
int main(int, char**)
void test()
{
{
unsigned a[5] = {5, 4, 3, 2, 1};
std::seed_seq s(a, a+5);
assert(s.size() == 5);
unsigned b[5] = {0};
s.param(b);
assert(b[0] == 5);
@ -30,6 +32,44 @@ int main(int, char**)
assert(b[2] == 3);
assert(b[3] == 2);
assert(b[4] == 1);
}
{
// Test truncation to 32 bits
unsigned long long a[4] = {
0x1234000056780000uLL,
0x0000001234567800uLL,
0xFFFFFFFFFFFFFFFFuLL,
0x0000000180000000uLL,
};
std::seed_seq s(a, a+4);
assert(s.size() == 4);
unsigned b[4] = {0};
s.param(b);
assert(b[0] == 0x56780000u);
assert(b[1] == 0x34567800u);
assert(b[2] == 0xFFFFFFFFu);
assert(b[3] == 0x80000000u);
}
#if TEST_STD_VER >= 11
{
// Test uniform initialization syntax (LWG 3422)
unsigned a[3] = {1, 2, 3};
std::seed_seq s{a, a+3}; // uniform initialization
assert(s.size() == 3);
unsigned b[3] = {0};
s.param(b);
assert(b[0] == 1);
assert(b[1] == 2);
assert(b[2] == 3);
}
#endif // TEST_STD_VER >= 11
}
int main(int, char**)
{
test();
return 0;
}

View File

@ -0,0 +1,30 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// <random>
// class seed_seq;
// template<class InputIterator>
// seed_seq(InputIterator begin, InputIterator end);
// Mandates: iterator_traits<InputIterator>::value_type is an integer type.
#include <random>
void test()
{
{
bool a[2] = {true, false};
std::seed_seq s(a, a+2); // OK
}
{
double a[2] = {1, 2};
std::seed_seq s(a, a+2); // expected-error@*:* {{Mandates: iterator_traits<InputIterator>::value_type is an integer type}}
// expected-error@*:* {{invalid operands to binary expression ('double' and 'unsigned int')}}
}
}