Remove PR 92268 workaround and fix new test failures
With the compiler bug fixed we can simplify the __sizable concept to use a return-type-requirement again. I also realised it was redundantly re-checking a subset of the sized_sentinel_for requirements. The compiler fix also revealed bugs in two tests which started to fail and are fixed by this patch. * include/bits/range_access.h (__sizable): Rename to __sentinel_size. Remove workaround for PR c++/92268 and remove redundant requirements that are already checked by sized_sentinel_for. * testsuite/std/ranges/access/cend.cc: Fix failures. * testsuite/std/ranges/access/end.cc: Likewise. From-SVN: r277667
This commit is contained in:
parent
beaecb2d6b
commit
b3ffa117e5
4 changed files with 36 additions and 27 deletions
|
@ -1,5 +1,11 @@
|
|||
2019-10-31 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
* include/bits/range_access.h (__sizable): Rename to __sentinel_size.
|
||||
Remove workaround for PR c++/92268 and remove redundant requirements
|
||||
that are already checked by sized_sentinel_for.
|
||||
* testsuite/std/ranges/access/cend.cc: Fix failures.
|
||||
* testsuite/std/ranges/access/end.cc: Likewise.
|
||||
|
||||
* include/bits/range_access.h (ranges::begin): Combine array and
|
||||
non-array overloads into one function template. Only use ADL for
|
||||
classes and enums.
|
||||
|
|
|
@ -689,19 +689,13 @@ namespace ranges
|
|||
-> __detail::__is_integer_like;
|
||||
};
|
||||
|
||||
// FIXME: needed due to PR c++/92268
|
||||
template<forward_iterator _It, sized_sentinel_for<_It> _End>
|
||||
requires requires (_It __it, _End __end)
|
||||
{ { __end - __it } -> __detail::__is_integer_like; }
|
||||
void
|
||||
__subtractable_fwd_iter(_It, _End)
|
||||
{ }
|
||||
|
||||
template<typename _Tp>
|
||||
concept __sizable = requires(_Tp&& __t)
|
||||
concept __sentinel_size = requires(_Tp&& __t)
|
||||
{
|
||||
__subtractable_fwd_iter(_Begin{}(std::forward<_Tp>(__t)),
|
||||
_End{}(std::forward<_Tp>(__t)));
|
||||
{ _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
|
||||
|
||||
{ _End{}(std::forward<_Tp>(__t)) }
|
||||
-> sized_sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
|
||||
};
|
||||
|
||||
struct _Size
|
||||
|
@ -717,7 +711,7 @@ namespace ranges
|
|||
return noexcept(__decay_copy(std::declval<_Tp>().size()));
|
||||
else if constexpr (__adl_size<_Tp>)
|
||||
return noexcept(__decay_copy(size(std::declval<_Tp>())));
|
||||
else if constexpr (__sizable<_Tp>)
|
||||
else if constexpr (__sentinel_size<_Tp>)
|
||||
return noexcept(_End{}(std::declval<_Tp>())
|
||||
- _Begin{}(std::declval<_Tp>()));
|
||||
}
|
||||
|
@ -725,7 +719,7 @@ namespace ranges
|
|||
public:
|
||||
template<typename _Tp>
|
||||
requires is_array_v<remove_reference_t<_Tp>>
|
||||
|| __member_size<_Tp> || __adl_size<_Tp> || __sizable<_Tp>
|
||||
|| __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp>
|
||||
constexpr auto
|
||||
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
|
||||
{
|
||||
|
@ -738,7 +732,7 @@ namespace ranges
|
|||
return std::forward<_Tp>(__e).size();
|
||||
else if constexpr (__adl_size<_Tp>)
|
||||
return size(std::forward<_Tp>(__e));
|
||||
else if constexpr (__sizable<_Tp>)
|
||||
else if constexpr (__sentinel_size<_Tp>)
|
||||
return __detail::__to_unsigned_like(
|
||||
_End{}(std::forward<_Tp>(__e))
|
||||
- _Begin{}(std::forward<_Tp>(__e)));
|
||||
|
|
|
@ -66,15 +66,18 @@ struct RR
|
|||
long l = 0;
|
||||
int a[4] = { 0, 1, 2, 3 };
|
||||
|
||||
const void* begin() const { return nullptr; }
|
||||
friend const void* begin(const RR&&) noexcept { return nullptr; }
|
||||
|
||||
short* end() noexcept { return &s; }
|
||||
const long* end() const { return &l; }
|
||||
const void* begin() const; // return type not an iterator
|
||||
|
||||
friend int* end(RR&) { throw 1; }
|
||||
short* end() noexcept { return &s; }
|
||||
|
||||
friend const long* begin(const RR&) noexcept;
|
||||
const long* end() const { return &l; }
|
||||
|
||||
friend int* begin(RR&&) noexcept;
|
||||
friend int* end(RR&& r) { return r.a + 1; }
|
||||
friend const int* end(const RR&) { throw 1; }
|
||||
|
||||
friend const int* begin(const RR&&) noexcept;
|
||||
friend const int* end(const RR&& r) noexcept { return r.a + 3; }
|
||||
};
|
||||
|
||||
|
|
|
@ -61,11 +61,12 @@ struct R
|
|||
{
|
||||
int a[4] = { 0, 1, 2, 3 };
|
||||
|
||||
const int* begin() const { return nullptr; }
|
||||
friend const int* begin(const R&& r) noexcept { return nullptr; }
|
||||
const int* begin() const;
|
||||
friend int* begin(R&&) noexcept;
|
||||
friend const int* begin(const R&&) noexcept;
|
||||
|
||||
// Should be ignored because it doesn't return a sentinel for int*
|
||||
const long* end() const { return nullptr; }
|
||||
const long* end() const;
|
||||
|
||||
friend int* end(R& r) { return r.a + 0; }
|
||||
friend int* end(R&& r) { return r.a + 1; }
|
||||
|
@ -105,15 +106,20 @@ struct RR
|
|||
long l = 0;
|
||||
int a[4] = { 0, 1, 2, 3 };
|
||||
|
||||
const void* begin() const { return nullptr; }
|
||||
friend const void* begin(const RR&&) noexcept { return nullptr; }
|
||||
const void* begin() const; // return type not an iterator
|
||||
|
||||
friend const short* begin(RR&) noexcept;
|
||||
short* end() noexcept { return &s; }
|
||||
|
||||
friend const long* begin(const RR&) noexcept;
|
||||
const long* end() const { return &l; }
|
||||
|
||||
friend int* end(RR&) { throw 1; }
|
||||
friend const int* begin(RR&&) noexcept;
|
||||
friend int* end(RR&) { throw 1; } // not valid for rvalues
|
||||
friend int* end(RR&& r) { return r.a + 1; }
|
||||
friend const int* end(const RR&) { throw 1; }
|
||||
|
||||
friend const int* begin(const RR&&) noexcept;
|
||||
friend const int* end(const RR&) { throw 1; } // not valid for rvalues
|
||||
friend const int* end(const RR&& r) noexcept { return r.a + 3; }
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue