https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114400

            Bug ID: 114400
           Summary: The resolution of LWG3950 seems incorrectly
                    implemented
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Keywords: rejects-valid
          Severity: normal
          Priority: P3
         Component: libstdc++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: de34 at live dot cn
  Target Milestone: ---

The following example fails to compile with libstdc++ due to ambiguity in
overload resolution (https://godbolt.org/z/Ya5o4rrKj).


```
#include <string>
#include <string_view>
#include <type_traits>

namespace test {
    template<class Traits>
    concept characterized_traits = requires { typename
Traits::is_characterized; };

    template<class CharT>
    struct test_traits : std::char_traits<CharT> {
        using is_characterized = void;
    };

    template<class Traits>
    struct traits_comparison_category {
        using type = std::weak_ordering;
    };
    template<class Traits>
        requires requires { typename Traits::comparison_category; }
    struct traits_comparison_category<Traits> {
        using type = Traits::comparison_category;
        static_assert(std::disjunction_v<
            std::is_same<type, std::partial_ordering>,
            std::is_same<type, std::weak_ordering>,
            std::is_same<type, std::strong_ordering>>);
    };

    // N.B. std::type_identity_t is exactly used.

    template<class CharT, characterized_traits Traits>
    constexpr bool operator==(
        std::basic_string_view<CharT, Traits> x,
        std::type_identity_t<std::basic_string_view<CharT, Traits>> y) noexcept
    {
        return x.size() == y.size() && x.compare(y) == 0;
    }

    template<class CharT, characterized_traits Traits>
    constexpr traits_comparison_category<Traits>::type operator<=>(
        std::basic_string_view<CharT, Traits> x,
        std::type_identity_t<std::basic_string_view<CharT, Traits>> y) noexcept
    {
        return
static_cast<traits_comparison_category<Traits>::type>(x.compare(y) <=> 0);
    }

    using test_string_view = std::basic_string_view<char, test_traits<char>>;
    static_assert(test_string_view{} == test_string_view{});
    static_assert(test_string_view{} == "");
    static_assert("" == test_string_view{});

    static_assert(test_string_view{} <=> test_string_view{} ==
std::strong_ordering::equal);
    static_assert(test_string_view{} <=> "" == std::strong_ordering::equal);
    static_assert("" <=> test_string_view{} == std::strong_ordering::equal);
}
```

The resolution of LWG3950 (https://cplusplus.github.io/LWG/issue3950) uses
`type_identity_t`, while libstdc++ currently uses `__type_identity_t`. The
difference between two alias templates can be observed by partial ordering
introduced by associated constraints.

Related PR in MSVC STL:
https://github.com/microsoft/STL/pull/4249

Reply via email to