sized_range
and ranges::size
redundantly use disable_sized_range
Section: 25.4.3 [range.sized] Status: C++20 Submitter: Casey Carter Opened: 2019-08-26 Last modified: 2021-02-25
Priority: 1
View all other issues in [range.sized].
View all issues with C++20 status.
Discussion:
disable_sized_range
(25.4.3 [range.sized]) is an opt-out trait that users may
specialize when their range
type conforms to the syntax of sized_range
but not its
semantics, or when the type is so poorly suited to the Standard Library that even testing the
validity of the expressions r.size()
or size(r)
for a range r
is
impossible. The library inspects disable_sized_range
in two places. (1) In the definition of
the sized_range
concept:
If the pertinent specialization oftemplate<class T> concept sized_range = range<T> && !disable_sized_range<remove_cvref_t<T>> && requires(T& t) { ranges::size(t); };
disable_sized_range
is true
, we avoid checking
the validity of the expression ranges::size(t)
in the requires-expression.
(2) In the definition of the ranges::size
CPO itself (25.3.10 [range.prim.size]),
the validity of the expressions decay-copy(E.size())
and
decay-copy(size(E))
is not checked if the pertinent specialization of
disable_sized_range
is true
.
disable_sized_range
is effectively checked twice when evaluating
sized_range
. This redundancy could be forgiven, if it did not permit the existence of
non-sized_range
s for which ranges::size
returns a valid size:
We should remove this gap betweenstruct mytype {}; using A = mytype[42]; template <> constexpr bool std::ranges::disable_sized_range<A> = true; static_assert(std::ranges::range<A>); static_assert(!std::ranges::sized_range<A>); static_assert(std::ranges::size(A{}) == 42); struct myrange { constexpr int* begin() const { return nullptr; } constexpr int* end() const { return nullptr; } }; template <> constexpr bool std::ranges::disable_sized_range<myrange> = true; static_assert(std::ranges::range<myrange>); static_assert(!std::ranges::sized_range<myrange>); static_assert(std::ranges::size(myrange{}) == 0);
ranges::size
and sized_range
by checking
disable_sized_range
only in the definition of ranges::size
, and continuing to rely
on the validity of ranges::size
in the sized_range
concept.
[2019-09-14 Priority set to 1 based on reflector discussion]
[2019-11 Wednesday night issue processing in Belfast.]
Status to Ready
Proposed resolution:
This wording is relative to N4830.
Modify 25.4.3 [range.sized] as follows:
template<class T> concept sized_range = range<T> &&!disable_sized_range<remove_cvref_t<T>> &&requires(T& t) { ranges::size(t); };