Consider the following code snippet:
#include <ranges>
auto r = std::views::iota(0) | std::views::take(0);
static_assert(std::ranges::sized_range<decltype(r)>);
gcc-trunk rejects it for required-expression std::ranges::size(r)
is invalid. Why does r
not model ranges::sized_range
, i,e, why can't I use std::ranges::size
on it?
Update
Compiles after using range-v3. Is this feature required for C++23, or is it an LWG issue?
#include <range/v3/all.hpp>
#include <ranges>
auto r = ranges::views::iota(0) | ranges::views::take(0);
static_assert(std::ranges::sized_range<decltype(r)>);
The problem seems to be that the sentinel_t
of r
in range-v3
is just ranges::default_sentinel
which satisfies the std::sized_sentinel_for<ranges::counted_iterator>
, since there is a valid operator-
in [predef.iterators#iterators.counted] for those two types:
friend constexpr iter_difference_t<I> operator-( const counted_iterator& x, default_sentinel_t); friend constexpr iter_difference_t<I> operator-( default_sentinel_t, const counted_iterator& y);
But in namepace std::ranges
, the sentinel_t
of r
is std::ranges::take_view<std::ranges::iota_view>::_Sentinel<true>
which cannot convert to std::default_sentinel_t
.