Created on 2023-10-28.00:00:00 last changed 13 months ago
Proposed resolution:
This wording is relative to N4964.
Modify [view.interface], class template view_interface synopsis, as indicated:
namespace std::ranges { template<class D> requires is_class_v<D> && same_as<D, remove_cv_t<D>> class view_interface { […] public: […] constexpr decltype(auto) back() requires (bidirectional_range<D> && common_range<D>) || (random_access_range<D> && sized_range<D>); constexpr decltype(auto) back() const requires (bidirectional_range<const D> && common_range<const D>) || (random_access_range<const D> && sized_range<const D>); […] }; }
Modify [view.interface.members] as indicated:
constexpr decltype(auto) back() requires (bidirectional_range<D> && common_range<D>) || (random_access_range<D> && sized_range<D>); constexpr decltype(auto) back() const requires (bidirectional_range<const D> && common_range<const D>) || (random_access_range<const D> && sized_range<const D>);-3- Preconditions: !empty() is true.
-4- Effects: Equivalent to:auto common-arg-end = []<class R>(R& r) { if constexpr (common_range<R>) { return ranges::end(r); } else { return ranges::begin(r) + ranges::distance(r); } }; return *ranges::prev(common-arg-endranges::end(derived()));
[ 2023-11-07; Reflector poll ]
NAD. "During the concat
discussion LEWG decided not to
support the corner case of random-access sized but not-common ranges."
"If we did want to address such ranges, would be better to enforce commonness
for random-access sized ranges by having ranges::end
return
ranges::begin(r) + ranges::size(r)
."
Currently, view_interface only provides the back member when the derived class satisfies both bidirectional_range and common_range, which ensures that ranges::prev can act its sentinel.
However, requiring common_range seems to be too strict because when the derived class satisfies both random_access_range and sized_range, its end iterator can still be calculated in constant time, which is what some range adaptors currently do to greedily become common ranges. I think we should follow similar rules to eliminate this inconsistency (demo):
#include <ranges>
constexpr auto r = std::ranges::subrange(std::views::iota(0), 5);
constexpr auto z = std::views::zip(r);
static_assert(r.back() == 4); // ill-formed
static_assert(std::get<0>(z.back()) == 4); // ok
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-11-07 18:35:04 | admin | set | messages: + msg13823 |
2023-11-07 18:35:04 | admin | set | status: new -> nad |
2023-10-28 16:14:08 | admin | set | messages: + msg13777 |
2023-10-28 00:00:00 | admin | create |