c++c++23const-iterator

How does std::basic_const_iterator support `it1 - it2`


Maybe it's a silly question, but I'm stuck on it now.

How does the following code work?

// g++ main.cpp -std=c++23

#include <iterator>

int main() {
    using It = std::basic_const_iterator<int*>;
    using CIt = std::basic_const_iterator<const int*>;

    It it1, it2;
    CIt cit;
    auto d1 = it1 - it2;  // ?
    auto d2 = it1 - cit;  // ?
}

From cppreference and GCC source, there is no operator - for two basic_const_iterators. The defined operator -s are:

Could someone explain how it1 - it2 and it1 - cit would work? Thanks!


Solution

  • As many others have commented (thanks!), it1 - it2 calls it1.operator -(it2), or precisely:

    template< std::sized_sentinel_for<Iter> S >
    constexpr difference_type operator-( const S& s ) const;
    

    cppreference

    But still I wasn't satisfied because they didn't explain why. So I did a bit research myself.

    Here is how it works:

    (using It = basic_const_iterator<int *>)

    The missing part of the puzzle was int* == It, until I tried the following code:

    struct A {
        constexpr bool operator ==(int) const { return true; }
    };
    
    int main() {
        static_assert(1 == A{});
    }
    

    int == A can be synthesized from A::operator ==(int) in the new C++! (Seems the feature was introduced in C++20. Could someone point me to the Standard?)

    So finally:

    Update

    Actually, operator <=> has the same synthesising, but not 2nd comparisons (!=, <, >, <=, >=):

    #include <compare>
    
    struct A {
        constexpr bool operator ==(int) const { return true; }
        constexpr auto operator <=>(int) const { return std::strong_ordering::equal; }
    };
    
    int main() {
        static_assert(1 == A{});
        static_assert((1 <=> A{}) == std::strong_ordering::equal);
    }