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.
const
overloads of take_while_view::begin/end
are underconstrainedSection: 25.7.11.2 [range.take.while.view] Status: C++23 Submitter: Tim Song Opened: 2020-06-06 Last modified: 2023-11-22
Priority: 0
View all other issues in [range.take.while.view].
View all issues with C++23 status.
Discussion:
The const
overloads of take_while_view::begin
and take_while_view::end
are underconstrained: they should require
the predicate to model indirect_unary_predicate<iterator_t<const V>>
.
A simple example is
#include <ranges> auto v = std::views::single(1) | std::views::take_while([](int& x) { return true;}); static_assert(std::ranges::range<decltype(v)>); static_assert(std::ranges::range<decltype(v) const>); bool b = std::ranges::cbegin(v) == std::ranges::cend(v);
Here, the static_assert
s pass but the comparison fails to compile. The other
views using indirect_unary_predicate
(filter_view
and
drop_while_view
) do not have this problem because they do not support
const-iteration.
[2020-07-17; Moved to Ready in telecon]
[2020-11-09 Approved In November virtual meeting. Status changed: Ready → WP.]
Proposed resolution:
This wording is relative to N4861.
Modify 25.7.11.2 [range.take.while.view], class template take_while_view
synopsis, as indicated:
namespace std::ranges { template<view V, class Pred> requires input_range<V> && is_object_v<Pred> && indirect_unary_predicate<const Pred, iterator_t<V>> class take_while_view : public view_interface<take_while_view<V, Pred>> { […] constexpr auto begin() requires (!simple-view<V>) { return ranges::begin(base_); } constexpr auto begin() const requires range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>> { return ranges::begin(base_); } constexpr auto end() requires (!simple-view<V>) { return sentinel<false>(ranges::end(base_), addressof(*pred_)); } constexpr auto end() const requires range<const V> && indirect_unary_predicate<const Pred, iterator_t<const V>> { return sentinel<true>(ranges::end(base_), addressof(*pred_)); } }; }