Issue 4074: compatible-joinable-ranges is underconstrained (original) (raw)
This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of WP status.
4074. _compatible-joinable-ranges_
is underconstrained
Section: 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_
.
However, unlike what 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(i).
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 only
common_with<range_value_t, range_value_t> &&
common_reference_with<range_reference_t, range_reference_t> &&
common_reference_with<range_rvalue_reference_t, range_rvalue_reference_t>;
[…]
}
[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 // see 17.12.1 [compare.syn]
#include // see 17.11.2 [initializer.list.syn]
#include // see 24.2 [iterator.synopsis]namespace std::ranges {
[…]
// 25.7.15 [range.join.with], join with view
template<class R, class P>concept compatible-joinable-ranges = see below; // exposition onlytemplate<input_range V, forward_range Pattern>
requiresview && input_range<range_reference_t>&& view&& compatible-joinable-ranges<range_reference_t, Pattern>
see below
class join_with_view; // freestanding
[…]
} 2. Modify 25.7.15.2 [range.join.with.view] as indicated:
namespace std::ranges {
template<class R, class P>concept compatible-joinable-ranges = // exposition onlycommon_with<range_value_t, range_value_t> &&
common_reference_with<range_reference_t, range_reference_t> &&
common_reference_with<range_rvalue_reference_t, range_rvalue_reference_t>;
[…]
template<input_range V, forward_range Pattern>
requires view && input_range<range_reference_t>
&& view
&&compatible-joinable-rangesconcatable<range_reference_t, Pattern>
class join_with_view : public view_interface<join_with_view<V, Pattern>> {
[…]
constexpr auto begin() const
requires forward_range &&
forward_range &&
is_reference_v<range_reference_t> &&
input_range<range_reference_t> &&
concatable<range_reference_t, const Pattern> {
return iterator{*this, ranges::begin(base)};
}
[…]
constexpr auto end() const
requires forward_range && forward_range &&
is_reference_v<range_reference_t> &&
input_range<range_reference_t> &&
concatable<range_reference_t, const Pattern> {
[…]
}
};
} 3. Modify 25.7.15.3 [range.join.with.iterator] as indicated:
namespace std::ranges {
template<input_range V, forward_range Pattern>
requires view && input_range<range_reference_t>
&& view &&compatible-joinable-rangesconcatable<range_reference_t, Pattern>
template
class join_with_view<V, Pattern>::iterator {
[…]
};
} 4. Modify 25.7.15.4 [range.join.with.sentinel] as indicated:
namespace std::ranges {
template<input_range V, forward_range Pattern>
requires view && input_range<range_reference_t>
&& view &&compatible-joinable-rangesconcatable<range_reference_t, Pattern>
template
class join_with_view<V, Pattern>::sentinel {
[…]
};
}