Why does std::basic_string_view have two equality comparison operators?

A quote from the standard regarding std::basic_string_view equality comparison operators (see http://eel.is/c++draft/string.view#comparison):

[Example 1: A sample conforming implementation for operator== would be:

template<class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> lhs,
                        basic_string_view<charT, traits> rhs) noexcept {
    return lhs.compare(rhs) == 0;
}
template<class charT, class traits>
constexpr bool operator==(basic_string_view<charT, traits> lhs,
                        type_identity_t<basic_string_view<charT, traits>> rhs) noexcept {
    return lhs.compare(rhs) == 0;
}

— end example]

Won't the second comparison operator be sufficient for all use cases? If the answer is no please provide the example code that will stop working (or will work differently) if the first comparison operator is removed. If the answer is yes then why does the C++ standard explicitly require the first operator to be defined?

1 answer

  • answered 2022-01-25 15:13 Barry

    I think this is insufficient reduction as a result of the adoption of <=> in P1614. Before that paper, there were three ==s in the example:

    template<class charT, class traits>
        constexpr bool operator==(basic_string_view<charT, traits> lhs,
                                  basic_string_view<charT, traits> rhs) noexcept {
          return lhs.compare(rhs) == 0;
        }
      template<class charT, class traits>
        constexpr bool operator==(basic_string_view<charT, traits> lhs,
                                  type_identity_t<basic_string_view<charT, traits>> rhs) noexcept {
          return lhs.compare(rhs) == 0;
        }
     template<class charT, class traits>
       constexpr bool operator==(type_identity_t<basic_string_view<charT, traits>> lhs,
                                 basic_string_view<charT, traits> rhs) noexcept {
         return lhs.compare(rhs) == 0;
       }
    

    At the time, we needed three operators. The type_identity ones handle stuff like sv == literal and literal == sv, and then you need the homogeneous one to disambiguate sv == sv.

    With the <=> adoption (or, more precisely, the == changes from P1185), == becomes symmetric so you don't need both type_identity operators to handle literal == sv, just the one suffices. I was basically mechanically going through and dropping unnecessary == and != overloads, so I removed that second.

    But what I did not realize is with the other one gone, we now no longer need the homogeneous comparison to disambiguate from the other two (we don't have other two anymore, just other one) - it's enough to just have the one type_identity overload.

    You could open an editorial issue to remove the homogeneous one. Or not, it's just an example anyway.

How many English words
do you know?
Test your English vocabulary size, and measure
how many words do you know
Online Test
Powered by Examplum