compatible-joinable-ranges
is underconstrainedSection: 25.7.15.2 [range.join.with.view] Status: WP Submitter: Hewill Kang Opened: 2024-04-21 Last modified: 2024-07-08
Priority: Not Prioritized
View all other issues in [range.join.with.view].
View all issues with WP status.
Discussion:
join_with_view
requires the value type, reference and rvalue reference of the inner range
and pattern range to share common (reference) types through compatible-joinable-ranges
.
concat_view
and generator
do, this concept only requires that
these three types be valid and does not further check the relationship between them to be compatible
with the indirectly_readable
requirement for input_iterator
.
This results in a validly-constructed join_with_view
that may not model input_range
,
which seems unintended.
The proposed resolution aliases compatible-joinable-ranges
to concatable
i.e. specialization for two ranges to fully constrain, and I believe this could also be a better fit for
LWG 3971.
Previous resolution [SUPERSEDED]:
This wording is relative to N4981.
Modify 25.7.15.2 [range.join.with.view] as indicated:
namespace std::ranges { template<class R, class P> concept compatible-joinable-ranges = concatable<R, P>; // exposition onlycommon_with<range_value_t<R>, range_value_t<P>> && common_reference_with<range_reference_t<R>, range_reference_t<P>> && common_reference_with<range_rvalue_reference_t<R>, range_rvalue_reference_t<P>>;[…] }
[2024-04-24; Hewill Kang provides improved wording]
[2024-05-08; Reflector poll]
Set status to Tentatively Ready after five votes in favour during reflector poll.
[St. Louis 2024-06-29; Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4981.
Modify 25.2 [ranges.syn] as indicated:
#include <compare> // see 17.11.1 [compare.syn] #include <initializer_list> // see 17.10.2 [initializer.list.syn] #include <iterator> // see 24.2 [iterator.synopsis] namespace std::ranges { […] // 25.7.15 [range.join.with], join with viewtemplate<class R, class P> concept compatible-joinable-ranges = see below; // exposition onlytemplate<input_range V, forward_range Pattern> requiresview<V> && input_range<range_reference_t<V>> && view<Pattern> && compatible-joinable-ranges<range_reference_t<V>, Pattern>see below class join_with_view; // freestanding […] }
Modify 25.7.15.2 [range.join.with.view] as indicated:
namespace std::ranges {template<class R, class P> concept compatible-joinable-ranges = // exposition only common_with<range_value_t<R>, range_value_t<P>> && common_reference_with<range_reference_t<R>, range_reference_t<P>> && common_reference_with<range_rvalue_reference_t<R>, range_rvalue_reference_t<P>>;[…] template<input_range V, forward_range Pattern> requires view<V> && input_range<range_reference_t<V>> && view<Pattern> &&compatible-joinable-rangesconcatable<range_reference_t<V>, Pattern> class join_with_view : public view_interface<join_with_view<V, Pattern>> { […] constexpr auto begin() const requires forward_range<const V> && forward_range<const Pattern> && is_reference_v<range_reference_t<const V>> && input_range<range_reference_t<const V>> && concatable<range_reference_t<const V>, const Pattern> { return iterator<true>{*this, ranges::begin(base_)}; } […] constexpr auto end() const requires forward_range<const V> && forward_range<const Pattern> && is_reference_v<range_reference_t<const V>> && input_range<range_reference_t<const V>> && concatable<range_reference_t<const V>, const Pattern> { […] } }; }
Modify 25.7.15.3 [range.join.with.iterator] as indicated:
namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && input_range<range_reference_t<V>> && view<Pattern> &&compatible-joinable-rangesconcatable<range_reference_t<V>, Pattern> template<bool Const> class join_with_view<V, Pattern>::iterator { […] }; }
Modify 25.7.15.4 [range.join.with.sentinel] as indicated:
namespace std::ranges { template<input_range V, forward_range Pattern> requires view<V> && input_range<range_reference_t<V>> && view<Pattern> &&compatible-joinable-rangesconcatable<range_reference_t<V>, Pattern> template<bool Const> class join_with_view<V, Pattern>::sentinel { […] }; }