Title
three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>>
Status
new
Section
[move.iter.cons][reverse.iter.cons]
Submitter
Casey Carter

Created on 2020-04-26.00:00:00 last changed 1 month ago

Messages

Date: 2020-05-04.18:38:43

Proposed resolution:

This wording is relative to N4861.

  1. Modify [move.iter.cons] as indicated:

    [Drafting note: this incorporates and supercedes the P/R of LWG 3265.]

    constexpr move_iterator();
    

    -1- Effects: Constructs a move_iterator, vValue-initializesing current. Iterator operations applied to the resulting iterator have defined behavior if and only if the corresponding operations are defined on a value-initialized iterator of type Iterator.

    constexpr explicit move_iterator(Iterator i);
    

    -2- Effects: Constructs a move_iterator, iInitializesing current with std::move(i).

    template<class U> constexpr move_iterator(const move_iterator<U>& u);
    

    -3- Mandates: U is convertible to IteratorConstraints: is_same_v<U, Iterator> is false and const U& models convertible_to<Iterator>.

    -4- Effects: Constructs a move_iterator, iInitializesing current with u.currentbase().

    template<class U> constexpr move_iterator& operator=(const move_iterator<U>& u);
    

    -5- Mandates: U is convertible to IteratorConstraints: is_same_v<U, Iterator> is false, const U& models convertible_to<Iterator>, and assignable_from<Iterator&, const U&> is modeled.

    -6- Effects: Assigns u.currentbase() to current.

  2. Modify [reverse.iter.cons] as indicated:

    template<class U> constexpr reverse_iterator(const reverse_iterator<U>& u);
    

    -?- Constraints: is_same_v<U, Iterator> is false and const U& models convertible_to<Iterator>.

    -3- Effects: Initializes current with u.current.

    template<class U>
      constexpr reverse_iterator&
        operator=(const reverse_iterator<U>& u);
    

    -?- Constraints: is_same_v<U, Iterator> is false, const U& models convertible_to<Iterator>, and assignable_from<Iterator&, const U&> is modeled.

    -4- Effects: Assigns u.currentbase() to current.

    -5- Returns: *this.

Date: 2020-05-04.18:38:43

Despite that reverse_iterator<int*> and reverse_iterator<const int*> are comparable with <=>, three_way_comparable_with<reverse_iterator<int*>, reverse_iterator<const int*>> is false. This unfortunate state of affairs results from the absence of constraints on reverse_iterator's converting constructor: both convertible_to<reverse_iterator<int*>, reverse_iterator<const int*>> and convertible_to<reverse_iterator<const int*>, reverse_iterator<int*>> evaluate to true, despite that reverse_iterator<int*>'s converting constructor template is ill-formed when instantiated for reverse_iterator<const int*>. This apparent bi-convertibility results in ambiguity when trying to determine common_reference_t<const reverse_iterator<int*>&, const reverse_iterator<const int*>&>, causing the common_reference requirement in three_way_comparable_with to fail.

I think we should correct this by constraining reverse_iterator's conversion constructor (and converting assignment operator, while we're here) correctly so we can use the concept to determine when it's ok to compare specializations of reverse_iterator with <=>.

move_iterator has similar issues due to its similarly unconstrained conversions. We should fix both similarly.

History
Date User Action Args
2020-04-27 16:11:51adminsetmessages: + msg11240
2020-04-26 00:00:00admincreate