This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++23 status.
std::ranges::repeat_view<T, IntegerClass>::iterator may be ill-formedSection: 25.6.5 [range.repeat] Status: C++23 Submitter: Jiang An Opened: 2023-02-05 Last modified: 2023-11-22
Priority: Not Prioritized
View all issues with C++23 status.
Discussion:
25.6.5.3 [range.repeat.iterator] specifies difference_type as
using difference_type = conditional_t<is-signed-integer-like<index-type>, index-type, IOTA-DIFF-T(index-type)>;
which always instantiates IOTA-DIFF-T(index-type), and thus possibly makes the program ill-formed when
index-type is an integer-class type (index-type is same as Bound in this case), because
IOTA-DIFF-T(index-type) is specified to be iter_difference_t<index-type>
which may be ill-formed (25.6.4.2 [range.iota.view]/1.1).
index-type as-is without instantiating IOTA-DIFF-T when
is-signed-integer-like<index-type> is true.
However, when Bound is an unsigned integer-class type, it's unclear which type should the difference type be,
or whether repeat_view should be well-formed when the possibly intended IOTA-DIFF-T(Bound) is ill-formed.
[2023-02-09 Tim adds wording]
We should reject types for which there is no usable difference type.
[Issaquah 2023-02-09; LWG]
Move to Immediate for C++23
[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate → WP.]
Proposed resolution:
This wording is relative to N4928.
Modify 25.2 [ranges.syn], header <ranges> synopsis, as indicated:
// […]
namespace std::ranges {
template<move_constructible W, semiregular Bound = unreachable_sentinel_t>
requires see below(is_object_v<W> && same_as<W, remove_cv_t<W>> &&
(is-integer-like<Bound> || same_as<Bound, unreachable_sentinel_t>))
class repeat_view;
Modify 25.6.5.2 [range.repeat.view] as indicated:
namespace std::ranges {
template<class T>
concept integer-like-with-usable-difference-type = //exposition only
is-signed-integer-like<T> || (is-integer-like<T> && weakly_incrementable<T>);
template<move_constructible W, semiregular Bound = unreachable_sentinel_t>
requires (is_object_v<W> && same_as<W, remove_cv_t<W>> &&
(is-integer-likeinteger-like-with-usable-difference-type<Bound> || same_as<Bound, unreachable_sentinel_t>))
class repeat_view {
[…]
};
}
Modify 25.6.5.3 [range.repeat.iterator] as indicated:
namespace std::ranges {
template<move_constructible W, semiregular Bound = unreachable_sentinel_t>
requires (is_object_v<W> && same_as<W, remove_cv_t<W>> &&
(is-integer-likeinteger-like-with-usable-difference-type<Bound> || same_as<Bound, unreachable_sentinel_t>))
class repeat_view<W, Bound>::iterator {
private:
using index-type = // exposition only
conditional_t<same_as<Bound, unreachable_sentinel_t>, ptrdiff_t, Bound>;
[…]
public:
[…]
using difference_type = see belowconditional_t<is-signed-integer-like<index-type>,
index-type,
IOTA-DIFF-T(index-type)>;
[…]
};
}
-?- If is-signed-integer-like<index-type> is true,
the member typedef-name difference_type denotes index-type.
Otherwise, it denotes IOTA-DIFF-T(index-type)
(25.6.4.2 [range.iota.view]).