зеркало из https://github.com/microsoft/STL.git
Implement LWG-3715: `view_interface::empty` is overconstrained (#2946)
Co-authored-by: Stephan T. Lavavej <stl@nuwen.net>
This commit is contained in:
Родитель
374fc90b6c
Коммит
06e7769550
|
@ -2722,24 +2722,32 @@ namespace ranges {
|
|||
public:
|
||||
#ifdef __clang__ // TRANSITION, LLVM-44833
|
||||
template <class _Dx = _Derived>
|
||||
_NODISCARD constexpr bool empty() requires forward_range<_Dx>
|
||||
_NODISCARD constexpr bool empty() requires sized_range<_Dx> || forward_range<_Dx>
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
_NODISCARD constexpr bool empty() requires forward_range<_Derived>
|
||||
_NODISCARD constexpr bool empty() requires sized_range<_Derived> || forward_range<_Derived>
|
||||
#endif // TRANSITION, LLVM-44833
|
||||
{
|
||||
auto& _Self = _Cast();
|
||||
return _RANGES begin(_Self) == _RANGES end(_Self);
|
||||
if constexpr (sized_range<_Derived>) {
|
||||
return _RANGES size(_Self) == 0;
|
||||
} else {
|
||||
return _RANGES begin(_Self) == _RANGES end(_Self);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __clang__ // TRANSITION, LLVM-44833
|
||||
template <class _Dx = _Derived>
|
||||
_NODISCARD constexpr bool empty() const requires forward_range<const _Dx>
|
||||
_NODISCARD constexpr bool empty() const requires sized_range<const _Dx> || forward_range<const _Dx>
|
||||
#else // ^^^ workaround / no workaround vvv
|
||||
_NODISCARD constexpr bool empty() const requires forward_range<const _Derived>
|
||||
_NODISCARD constexpr bool empty() const requires sized_range<const _Derived> || forward_range<const _Derived>
|
||||
#endif // TRANSITION, LLVM-44833
|
||||
{
|
||||
auto& _Self = _Cast();
|
||||
return _RANGES begin(_Self) == _RANGES end(_Self);
|
||||
if constexpr (sized_range<const _Derived>) {
|
||||
return _RANGES size(_Self) == 0;
|
||||
} else {
|
||||
return _RANGES begin(_Self) == _RANGES end(_Self);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __clang__ // TRANSITION, LLVM-44833
|
||||
|
|
|
@ -83,6 +83,10 @@ namespace test_view_interface {
|
|||
|
||||
S end();
|
||||
S end() const requires (to_bool(HasConstRange));
|
||||
|
||||
unsigned int size() requires (to_bool(Diff) && !std::derived_from<Cat, forward_iterator_tag>);
|
||||
unsigned int size() const requires (to_bool(HasConstRange) && to_bool(Diff)
|
||||
&& !std::derived_from<Cat, forward_iterator_tag>);
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
@ -133,13 +137,13 @@ namespace test_view_interface {
|
|||
STATIC_ASSERT(ranges::range<V>);
|
||||
STATIC_ASSERT(!ranges::range<V const>);
|
||||
STATIC_ASSERT(ranges::view<V>);
|
||||
STATIC_ASSERT(!CanEmpty<V&>);
|
||||
STATIC_ASSERT(CanEmpty<V&>);
|
||||
STATIC_ASSERT(!CanEmpty<V const&>);
|
||||
STATIC_ASSERT(!CanBool<V&>);
|
||||
STATIC_ASSERT(CanBool<V&>);
|
||||
STATIC_ASSERT(!CanBool<V const&>);
|
||||
STATIC_ASSERT(!CanData<V&>);
|
||||
STATIC_ASSERT(!CanData<V const&>);
|
||||
STATIC_ASSERT(!CanSize<V&>);
|
||||
STATIC_ASSERT(CanSize<V&>);
|
||||
STATIC_ASSERT(!CanSize<V const&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V const&>);
|
||||
|
@ -154,14 +158,14 @@ namespace test_view_interface {
|
|||
STATIC_ASSERT(ranges::range<V>);
|
||||
STATIC_ASSERT(ranges::range<V const>);
|
||||
STATIC_ASSERT(ranges::view<V>);
|
||||
STATIC_ASSERT(!CanEmpty<V&>);
|
||||
STATIC_ASSERT(!CanEmpty<V const&>);
|
||||
STATIC_ASSERT(!CanBool<V&>);
|
||||
STATIC_ASSERT(!CanBool<V const&>);
|
||||
STATIC_ASSERT(CanEmpty<V&>);
|
||||
STATIC_ASSERT(CanEmpty<V const&>);
|
||||
STATIC_ASSERT(CanBool<V&>);
|
||||
STATIC_ASSERT(CanBool<V const&>);
|
||||
STATIC_ASSERT(!CanData<V&>);
|
||||
STATIC_ASSERT(!CanData<V const&>);
|
||||
STATIC_ASSERT(!CanSize<V&>);
|
||||
STATIC_ASSERT(!CanSize<V const&>);
|
||||
STATIC_ASSERT(CanSize<V&>);
|
||||
STATIC_ASSERT(CanSize<V const&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V const&>);
|
||||
STATIC_ASSERT(!CanMemberBack<V&>);
|
||||
|
@ -217,13 +221,13 @@ namespace test_view_interface {
|
|||
STATIC_ASSERT(ranges::range<V>);
|
||||
STATIC_ASSERT(!ranges::range<V const>);
|
||||
STATIC_ASSERT(ranges::view<V>);
|
||||
STATIC_ASSERT(!CanEmpty<V&>);
|
||||
STATIC_ASSERT(CanEmpty<V&>);
|
||||
STATIC_ASSERT(!CanEmpty<V const&>);
|
||||
STATIC_ASSERT(!CanBool<V&>);
|
||||
STATIC_ASSERT(CanBool<V&>);
|
||||
STATIC_ASSERT(!CanBool<V const&>);
|
||||
STATIC_ASSERT(!CanData<V&>);
|
||||
STATIC_ASSERT(!CanData<V const&>);
|
||||
STATIC_ASSERT(!CanSize<V&>);
|
||||
STATIC_ASSERT(CanSize<V&>);
|
||||
STATIC_ASSERT(!CanSize<V const&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V const&>);
|
||||
|
@ -238,14 +242,14 @@ namespace test_view_interface {
|
|||
STATIC_ASSERT(ranges::range<V>);
|
||||
STATIC_ASSERT(ranges::range<V const>);
|
||||
STATIC_ASSERT(ranges::view<V>);
|
||||
STATIC_ASSERT(!CanEmpty<V&>);
|
||||
STATIC_ASSERT(!CanEmpty<V const&>);
|
||||
STATIC_ASSERT(!CanBool<V&>);
|
||||
STATIC_ASSERT(!CanBool<V const&>);
|
||||
STATIC_ASSERT(CanEmpty<V&>);
|
||||
STATIC_ASSERT(CanEmpty<V const&>);
|
||||
STATIC_ASSERT(CanBool<V&>);
|
||||
STATIC_ASSERT(CanBool<V const&>);
|
||||
STATIC_ASSERT(!CanData<V&>);
|
||||
STATIC_ASSERT(!CanData<V const&>);
|
||||
STATIC_ASSERT(!CanSize<V&>);
|
||||
STATIC_ASSERT(!CanSize<V const&>);
|
||||
STATIC_ASSERT(CanSize<V&>);
|
||||
STATIC_ASSERT(CanSize<V const&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V&>);
|
||||
STATIC_ASSERT(!CanMemberFront<V const&>);
|
||||
STATIC_ASSERT(!CanMemberBack<V&>);
|
||||
|
|
|
@ -219,7 +219,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
}
|
||||
|
||||
// Validate view_interface::empty and operator bool
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == forward_range<Rng>);
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == (sized_range<Rng> || forward_range<Rng>) );
|
||||
STATIC_ASSERT(CanBool<R> == CanEmpty<R>);
|
||||
if constexpr (CanMemberEmpty<R>) {
|
||||
assert(r.empty() == is_empty);
|
||||
|
|
|
@ -36,7 +36,7 @@ template <ranges::input_range Rng>
|
|||
constexpr bool test_one(Rng&& rng) {
|
||||
using ranges::elements_view, ranges::bidirectional_range, ranges::common_range, ranges::contiguous_range,
|
||||
ranges::enable_borrowed_range, ranges::forward_range, ranges::input_range, ranges::iterator_t, ranges::prev,
|
||||
ranges::random_access_range, ranges::range, ranges::range_reference_t, ranges::sentinel_t,
|
||||
ranges::random_access_range, ranges::range, ranges::range_reference_t, ranges::sentinel_t, ranges::sized_range,
|
||||
ranges::borrowed_range;
|
||||
|
||||
using V = views::all_t<Rng>;
|
||||
|
@ -157,7 +157,7 @@ constexpr bool test_one(Rng&& rng) {
|
|||
const bool is_empty = ranges::empty(expected_keys);
|
||||
|
||||
// Validate view_interface::empty and operator bool
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == forward_range<Rng>);
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == (sized_range<Rng> || forward_range<Rng>) );
|
||||
STATIC_ASSERT(CanBool<R> == CanEmpty<R>);
|
||||
if constexpr (CanMemberEmpty<R>) {
|
||||
assert(r.empty() == is_empty);
|
||||
|
@ -170,7 +170,7 @@ constexpr bool test_one(Rng&& rng) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == forward_range<const Rng>);
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == (sized_range<const Rng> || forward_range<const Rng>) );
|
||||
STATIC_ASSERT(CanBool<const R> == CanEmpty<const R>);
|
||||
if constexpr (CanMemberEmpty<const R>) {
|
||||
assert(as_const(r).empty() == is_empty);
|
||||
|
|
|
@ -219,7 +219,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
}
|
||||
|
||||
// Validate view_interface::empty and operator bool
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == forward_range<Rng>);
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == (sized_range<Rng> || forward_range<Rng>) );
|
||||
STATIC_ASSERT(CanBool<R> == CanEmpty<R>);
|
||||
if constexpr (CanMemberEmpty<R>) {
|
||||
assert(r.empty() == is_empty);
|
||||
|
@ -232,7 +232,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == forward_range<const Rng>);
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == (sized_range<const Rng> || forward_range<const Rng>) );
|
||||
STATIC_ASSERT(CanBool<const R> == CanEmpty<const R>);
|
||||
if constexpr (CanMemberEmpty<const R>) {
|
||||
assert(as_const(r).empty() == is_empty);
|
||||
|
|
|
@ -42,7 +42,7 @@ template <ranges::input_range Rng, ranges::random_access_range Expected>
|
|||
constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
||||
using ranges::transform_view, ranges::bidirectional_range, ranges::common_range, ranges::contiguous_range,
|
||||
ranges::enable_borrowed_range, ranges::forward_range, ranges::input_range, ranges::iterator_t, ranges::prev,
|
||||
ranges::random_access_range, ranges::range, ranges::range_reference_t, ranges::sentinel_t;
|
||||
ranges::random_access_range, ranges::sized_range, ranges::range, ranges::range_reference_t, ranges::sentinel_t;
|
||||
|
||||
constexpr bool is_view = ranges::view<remove_cvref_t<Rng>>;
|
||||
|
||||
|
@ -169,7 +169,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
constexpr bool const_invocable = regular_invocable<const Fun&, range_reference_t<const V>>;
|
||||
|
||||
// Validate view_interface::empty and operator bool
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == forward_range<Rng>);
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == (sized_range<Rng> || forward_range<Rng>) );
|
||||
STATIC_ASSERT(CanBool<R> == CanEmpty<R>);
|
||||
if constexpr (CanMemberEmpty<R>) {
|
||||
assert(r.empty() == is_empty);
|
||||
|
@ -182,7 +182,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == (forward_range<const Rng> && const_invocable));
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == ((sized_range<const Rng> || forward_range<const Rng>) &&const_invocable));
|
||||
STATIC_ASSERT(CanBool<const R> == CanEmpty<const R>);
|
||||
if constexpr (CanMemberEmpty<const R>) {
|
||||
assert(as_const(r).empty() == is_empty);
|
||||
|
|
|
@ -119,7 +119,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
}
|
||||
|
||||
// Validate view_interface::empty and operator bool
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == forward_range<V>);
|
||||
STATIC_ASSERT(CanMemberEmpty<R> == (sized_range<V> || forward_range<V>) );
|
||||
STATIC_ASSERT(CanBool<R> == CanEmpty<R>);
|
||||
if constexpr (CanMemberEmpty<R>) {
|
||||
assert(r.empty() == is_empty);
|
||||
|
@ -132,7 +132,8 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) {
|
|||
}
|
||||
}
|
||||
|
||||
STATIC_ASSERT(CanMemberEmpty<const R> == forward_range<const Rng>);
|
||||
STATIC_ASSERT(
|
||||
CanMemberEmpty<const R> == ((forward_range<Rng> && sized_range<const V>) || forward_range<const Rng>) );
|
||||
STATIC_ASSERT(CanBool<const R> == CanEmpty<const R>);
|
||||
if constexpr (CanMemberEmpty<const R>) {
|
||||
assert(as_const(r).empty() == is_empty);
|
||||
|
|
Загрузка…
Ссылка в новой задаче