Commit b3ffa117 by Jonathan Wakely Committed by Jonathan Wakely

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
parent beaecb2d
2019-10-31 Jonathan Wakely <jwakely@redhat.com> 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 * include/bits/range_access.h (ranges::begin): Combine array and
non-array overloads into one function template. Only use ADL for non-array overloads into one function template. Only use ADL for
classes and enums. classes and enums.
......
...@@ -689,19 +689,13 @@ namespace ranges ...@@ -689,19 +689,13 @@ namespace ranges
-> __detail::__is_integer_like; -> __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> template<typename _Tp>
concept __sizable = requires(_Tp&& __t) concept __sentinel_size = requires(_Tp&& __t)
{ {
__subtractable_fwd_iter(_Begin{}(std::forward<_Tp>(__t)), { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator;
_End{}(std::forward<_Tp>(__t)));
{ _End{}(std::forward<_Tp>(__t)) }
-> sized_sentinel_for<decltype(_Begin{}(std::forward<_Tp>(__t)))>;
}; };
struct _Size struct _Size
...@@ -717,7 +711,7 @@ namespace ranges ...@@ -717,7 +711,7 @@ namespace ranges
return noexcept(__decay_copy(std::declval<_Tp>().size())); return noexcept(__decay_copy(std::declval<_Tp>().size()));
else if constexpr (__adl_size<_Tp>) else if constexpr (__adl_size<_Tp>)
return noexcept(__decay_copy(size(std::declval<_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>()) return noexcept(_End{}(std::declval<_Tp>())
- _Begin{}(std::declval<_Tp>())); - _Begin{}(std::declval<_Tp>()));
} }
...@@ -725,7 +719,7 @@ namespace ranges ...@@ -725,7 +719,7 @@ namespace ranges
public: public:
template<typename _Tp> template<typename _Tp>
requires is_array_v<remove_reference_t<_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 constexpr auto
operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>())
{ {
...@@ -738,7 +732,7 @@ namespace ranges ...@@ -738,7 +732,7 @@ namespace ranges
return std::forward<_Tp>(__e).size(); return std::forward<_Tp>(__e).size();
else if constexpr (__adl_size<_Tp>) else if constexpr (__adl_size<_Tp>)
return size(std::forward<_Tp>(__e)); return size(std::forward<_Tp>(__e));
else if constexpr (__sizable<_Tp>) else if constexpr (__sentinel_size<_Tp>)
return __detail::__to_unsigned_like( return __detail::__to_unsigned_like(
_End{}(std::forward<_Tp>(__e)) _End{}(std::forward<_Tp>(__e))
- _Begin{}(std::forward<_Tp>(__e))); - _Begin{}(std::forward<_Tp>(__e)));
......
...@@ -66,15 +66,18 @@ struct RR ...@@ -66,15 +66,18 @@ struct RR
long l = 0; long l = 0;
int a[4] = { 0, 1, 2, 3 }; int a[4] = { 0, 1, 2, 3 };
const void* begin() const { return nullptr; } const void* begin() const; // return type not an iterator
friend const void* begin(const RR&&) noexcept { return nullptr; }
friend int* end(RR&) { throw 1; }
short* end() noexcept { return &s; } short* end() noexcept { return &s; }
friend const long* begin(const RR&) noexcept;
const long* end() const { return &l; } const long* end() const { return &l; }
friend int* end(RR&) { throw 1; } friend int* begin(RR&&) noexcept;
friend int* end(RR&& r) { return r.a + 1; } 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; } friend const int* end(const RR&& r) noexcept { return r.a + 3; }
}; };
......
...@@ -61,11 +61,12 @@ struct R ...@@ -61,11 +61,12 @@ struct R
{ {
int a[4] = { 0, 1, 2, 3 }; int a[4] = { 0, 1, 2, 3 };
const int* begin() const { return nullptr; } const int* begin() const;
friend const int* begin(const R&& r) noexcept { return nullptr; } friend int* begin(R&&) noexcept;
friend const int* begin(const R&&) noexcept;
// Should be ignored because it doesn't return a sentinel for int* // 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 + 0; }
friend int* end(R&& r) { return r.a + 1; } friend int* end(R&& r) { return r.a + 1; }
...@@ -105,15 +106,20 @@ struct RR ...@@ -105,15 +106,20 @@ struct RR
long l = 0; long l = 0;
int a[4] = { 0, 1, 2, 3 }; int a[4] = { 0, 1, 2, 3 };
const void* begin() const { return nullptr; } const void* begin() const; // return type not an iterator
friend const void* begin(const RR&&) noexcept { return nullptr; }
friend const short* begin(RR&) noexcept;
short* end() noexcept { return &s; } short* end() noexcept { return &s; }
friend const long* begin(const RR&) noexcept;
const long* end() const { return &l; } 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 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; } friend const int* end(const RR&& r) noexcept { return r.a + 3; }
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment