On Tue, Mar 11, 2025 at 10:28 PM Jonathan Wakely <jwak...@redhat.com> wrote:

> LWG 4112 (approved in Wrocław, November 2024) changes the has-arrow
> helper to require operator-> to be valid on a const-qualified lvalue.
> This affects the constraints for filter_view::_Iterator::operator-> and
> join_view::_Iterator::operator-> so that they can only be used if the
> underlying iterator supports operator-> on const.
>
> The change also adds semantic (i.e. not checkable and not enforced)
> requirements that operator-> must have the same semantics whether called
> on a const or non-const value, and on an lvalue or rvalue (due to the
> implicit expression variation rules in [concepts.equality]).
>
> libstdc++-v3/ChangeLog:
>
>         * include/bits/ranges_util.h (ranges::_detail::__has_arrow):
>         Require operator->() to be valid on const-qualified type, as per
>         LWG 4112.
>         * testsuite/std/ranges/adaptors/lwg4112.cc: New test.
> ---
>
> Tested x86_64-linux.
>
LGTM

>
>  libstdc++-v3/include/bits/ranges_util.h       |  5 ++-
>  .../testsuite/std/ranges/adaptors/lwg4112.cc  | 41 +++++++++++++++++++
>  2 files changed, 45 insertions(+), 1 deletion(-)
>  create mode 100644 libstdc++-v3/testsuite/std/ranges/adaptors/lwg4112.cc
>
> diff --git a/libstdc++-v3/include/bits/ranges_util.h
> b/libstdc++-v3/include/bits/ranges_util.h
> index 54e4f6261b0..53b7f5c17f1 100644
> --- a/libstdc++-v3/include/bits/ranges_util.h
> +++ b/libstdc++-v3/include/bits/ranges_util.h
> @@ -54,9 +54,12 @@ namespace ranges
>         && same_as<iterator_t<_Range>, iterator_t<const _Range>>
>         && same_as<sentinel_t<_Range>, sentinel_t<const _Range>>;
>
> +    // _GLIBCXX_RESOLVE_LIB_DEFECTS
> +    // 4112. has-arrow should required operator->() to be const-qualified
>      template<typename _It>
>        concept __has_arrow = input_iterator<_It>
> -       && (is_pointer_v<_It> || requires(_It __it) { __it.operator->();
> });
> +       && (is_pointer_v<_It>
> +             || requires(const _It __it) { __it.operator->(); });
>
>      using std::__detail::__different_from;
>    } // namespace __detail
> diff --git a/libstdc++-v3/testsuite/std/ranges/adaptors/lwg4112.cc
> b/libstdc++-v3/testsuite/std/ranges/adaptors/lwg4112.cc
> new file mode 100644
> index 00000000000..a283504b636
> --- /dev/null
> +++ b/libstdc++-v3/testsuite/std/ranges/adaptors/lwg4112.cc
> @@ -0,0 +1,41 @@
> +// { dg-do compile { target c++20 } }
> +
> +// LWG 4112. has-arrow should required operator->() to be const-qualified
> +
> +// The issue resolution means that range adaptors which use has-arrow to
> +// constrain their iterator's operator-> should require a const-qualified
> +// operator-> on the underlying view's iterator.
> +
> +#include <ranges>
> +
> +struct Int { int i = 0; };
> +
> +struct Iter
> +{
> +  using value_type = Int;
> +  using difference_type = int;
> +
> +  mutable Int val;
> +
> +  Int& operator*() const { return val; }
> +  Int* operator->() /* non-const */ { return &val; }
> +  Iter& operator++() { ++val.i; return *this; }
> +  void operator++(int) { ++val.i; }
> +  bool operator==(const Iter& j) const { return val.i == j.val.i; }
> +};
> +
> +template<typename T>
> +concept has_op_arrow = requires (T t) { t.operator->(); };
> +
> +static_assert( has_op_arrow<Iter> );
> +static_assert( ! has_op_arrow<const Iter> );
> +
> +using Range = std::ranges::subrange<Iter>;
> +using Pred = bool(*)(Int);
> +using FilterView = std::ranges::filter_view<Range, Pred>;
> +using FilterIterator = std::ranges::iterator_t<FilterView>;
> +
> +static_assert( ! has_op_arrow<FilterIterator> );
> +static_assert( ! has_op_arrow<FilterIterator&> );
> +static_assert( ! has_op_arrow<FilterIterator const> );
> +static_assert( ! has_op_arrow<FilterIterator const&> );
> --
> 2.48.1
>
>

Reply via email to