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.

3500. join_view::iterator::operator->() is bogus

Section: 25.7.14.3 [range.join.iterator] Status: C++23 Submitter: Michael Schellenberger Costa Opened: 2020-11-15 Last modified: 2023-11-22

Priority: 0

View all other issues in [range.join.iterator].

View all issues with C++23 status.

Discussion:

There seems to be a copy & paste error in the join_view::iterator::operator->() specification. According to 25.7.14.3 [range.join.iterator] p8 it is specified as:

constexpr iterator_t<Base> operator->() const
  requires has-arrow<iterator_t<Base>> && copyable<iterator_t<Base>>;

-8- Effects: Equivalent to return inner_;

Now inner_ is of type iterator_t<range_reference_t<Base>>. So it is unclear how that should be converted to iterator_t<Base>, or why the constraints concern the outer iterator type iterator_t<Base>. On the other hand returning outer_ would not make any sense here.

As far as I can tell we should replace iterator_t<Base> with iterator_t<range_reference_t<Base>> so that the new specification would read

constexpr iterator_t<range_reference_t<Base>> operator->() const
 requires has-arrow<iterator_t<range_reference_t<Base>>> 
   && copyable<iterator_t<range_reference_t<Base>>>;

-8- Effects: Equivalent to return inner_;

Generally it would help readability of the specification a lot if we would introduce some exposition only aliases:

using OuterIter = iterator_t<Base>; //exposition-only
using InnerIter = iterator_t<range_reference_t<Base>> //exposition-only

and use them throughout join_view::iterator.

[2020-11-21; Reflector prioritization]

Set priority to 0 and status to Tentatively Ready after six votes in favour during reflector discussions.

[2021-02-26 Approved at February 2021 virtual plenary. Status changed: Tentatively Ready → WP.]

Proposed resolution:

This wording is relative to N4868.

  1. Modify 25.7.14.3 [range.join.iterator], class template join_view::iterator synopsis, as indicated:

    template<input_range V>
      requires view<V> && input_range<range_reference_t<V>> &&
               (is_reference_v<range_reference_t<V>> ||
                view<range_value_t<V>>)
    struct join_view<V>::iterator {
    private:
      using Parent = // exposition only
        conditional_t<Const, const join_view, join_view>;
      using Base = conditional_t<Const, const V, V>; // exposition only
      using OuterIter = iterator_t<Base>; //exposition-only
      using InnerIter = iterator_t<range_reference_t<Base>> //exposition-only
      static constexpr bool ref-is-glvalue = // exposition only
        is_reference_v<range_reference_t<Base>>;
      OuterIteriterator_t<Base> outer_ = OuterIteriterator_t<Base>(); // exposition only
      InnerIteriterator_t<range_reference_t<Base>> inner_ = // exposition only
        InnerIteriterator_t<range_reference_t<Base>>();
      Parent* parent_ = nullptr; // exposition only
      constexpr void satisfy(); // exposition only
    public:
      […]
      iterator() = default;
      constexpr iterator(Parent& parent, OuterIteriterator_t<Base> outer);
      constexpr iterator(iterator<!Const> i)
        requires Const &&
                 convertible_to<iterator_t<V>, OuterIteriterator_t<Base>> &&
                 convertible_to<iterator_t<InnerRng>,
                                InnerIteriterator_t<range_reference_t<Base>>>;
    
      constexpr decltype(auto) operator*() const { return *inner_; }
      
      constexpr InnerIteriterator_t<Base> operator->() const
        requires has-arrow<InnerIteriterator_t<Base>> 
          && copyable<InnerIteriterator_t<Base>>;
      
      constexpr iterator& operator++();
      […]
    

    […]

    constexpr void satisfy(); // exposition only
    

    -5- Effects: Equivalent to:

    […]
    if constexpr (ref-is-glvalue)
      inner_ = InnerIteriterator_t<range_reference_t<Base>>();
    
    constexpr iterator(Parent& parent, OuterIteriterator_t<Base> outer);
    

    […]

    constexpr iterator(iterator<!Const> i)
      requires Const &&
               convertible_to<iterator_t<V>, OuterIteriterator_t<Base>> &&
               convertible_to<iterator_t<InnerRng>,
                              InnerIteriterator_t<range_reference_t<Base>>>;
    

    […]

    constexpr InnerIteriterator_t<Base> operator->() const
      requires has-arrow<InnerIteriterator_t<Base>> 
        && copyable<InnerIteriterator_t<Base>>;
    

    -8- Effects: Equivalent to return inner_;

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy