public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented
@ 2024-03-20  2:57 de34 at live dot cn
  2024-03-20  9:09 ` [Bug libstdc++/114400] " redi at gcc dot gnu.org
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: de34 at live dot cn @ 2024-03-20  2:57 UTC (permalink / raw)
  To: gcc-bugs

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
@ 2024-03-20  9:09 ` redi at gcc dot gnu.org
  2024-03-20  9:16 ` redi at gcc dot gnu.org
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2024-03-20  9:09 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #1 from Jonathan Wakely <redi at gcc dot gnu.org> ---
The resolution of LWG 3950 has not been implemented, at all. The use of
__type_identity_t there dates from 2019 (r10-1886-g0d67cd380d37f2) and replaced
earlier uses of common_type_t which date from the initial commit of
std::experimental::string_view (r0-126555-g77cba5af77ccf8).

The current code is 100% conforming, since the method of disambiguation is
unspecified currently.  LWG 3950 should be approved in a few days, and then
we'll have to decide what to do (we can't use type_identity unconditionally
because it doesn't exist in C++17, which is why I used __type_identity_t in the
first place).

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
  2024-03-20  9:09 ` [Bug libstdc++/114400] " redi at gcc dot gnu.org
@ 2024-03-20  9:16 ` redi at gcc dot gnu.org
  2024-03-20  9:18 ` redi at gcc dot gnu.org
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2024-03-20  9:16 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
One option would be to make __type_identity_t an alias for type_identity_t in
C++20:

--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -156,13 +156,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using __conditional_t
       = typename __conditional<_Cond>::template type<_If, _Else>;

+#ifdef __cpp_lib_type_identity // C++ >= 20
+  /** * Identity metafunction.
+   * @since C++20
+   * @{
+   */
+  template<typename _Tp>
+    struct type_identity { using type = _Tp; };
+
+  template<typename _Tp>
+    using type_identity_t = typename type_identity<_Tp>::type;
+  /// @}
+
+  template<typename _Tp>
+    using __type_identity_t = type_identity_t<_Tp>;
+  template<typename _Tp>
+    using __type_identity_t = type_identity_t<_Tp>;
+#else
   /// @cond undocumented
   template <typename _Type>
-    struct __type_identity
-    { using type = _Type; };
+    using __type_identity = type_identity<_Type>;

   template<typename _Tp>
     using __type_identity_t = typename __type_identity<_Tp>::type;
+#endif

   namespace __detail
   {
@@ -3600,19 +3617,6 @@ template<typename _Ret, typename _Fn, typename... _Args>
   /// @}
 #endif // __cpp_lib_remove_cvref

-#ifdef __cpp_lib_type_identity // C++ >= 20
-  /** * Identity metafunction.
-   * @since C++20
-   * @{
-   */
-  template<typename _Tp>
-    struct type_identity { using type = _Tp; };
-
-  template<typename _Tp>
-    using type_identity_t = typename type_identity<_Tp>::type;
-  /// @}
-#endif
-
 #ifdef __cpp_lib_unwrap_ref // C++ >= 20
   /** Unwrap a reference_wrapper
    * @since C++20

I don't think we have any uses of __type_identity or __type_identity_t where
this will cause ABI changes. None of the types using __type_identity_t in
constructors are explicitly instantiated in the library.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
  2024-03-20  9:09 ` [Bug libstdc++/114400] " redi at gcc dot gnu.org
  2024-03-20  9:16 ` redi at gcc dot gnu.org
@ 2024-03-20  9:18 ` redi at gcc dot gnu.org
  2024-03-20 10:02 ` de34 at live dot cn
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2024-03-20  9:18 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Oops, that was meant to be:

#ifdef __cpp_lib_type_identity // C++ >= 20
  /** * Identity metafunction.
   * @since C++20
   * @{
   */
  template<typename _Tp>
    struct type_identity { using type = _Tp; };

  template<typename _Tp>
    using type_identity_t = typename type_identity<_Tp>::type;
  /// @}

  template<typename _Tp>
    using __type_identity = type_identity<_Tp>;
  template<typename _Tp>
    using __type_identity_t = type_identity_t<_Tp>;
#else
  /// @cond undocumented
  template <typename _Type>
    using __type_identity
    { using type = _Type; };

  template<typename _Tp>
    using __type_identity_t = typename __type_identity<_Tp>::type;
#endif

But that messes up the @cond / @endcond nesting. Anyway, something like that.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
                   ` (2 preceding siblings ...)
  2024-03-20  9:18 ` redi at gcc dot gnu.org
@ 2024-03-20 10:02 ` de34 at live dot cn
  2024-03-20 10:07 ` redi at gcc dot gnu.org
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 8+ messages in thread
From: de34 at live dot cn @ 2024-03-20 10:02 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Jiang An <de34 at live dot cn> ---
(In reply to Jonathan Wakely from comment #1)
> The resolution of LWG 3950 has not been implemented, at all.

Hmm... r14-5349 seems "implementing the resolution" per the commit message.
Perhaps I misread something.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
                   ` (3 preceding siblings ...)
  2024-03-20 10:02 ` de34 at live dot cn
@ 2024-03-20 10:07 ` redi at gcc dot gnu.org
  2024-03-20 11:02 ` redi at gcc dot gnu.org
  2024-03-23 11:09 ` cvs-commit at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2024-03-20 10:07 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Jonathan Wakely <redi at gcc dot gnu.org> ---
It was simplifying the overload set, consistent with the proposed resolution of
3950.

If 3950 breaks existing implementations, then arguably 3950 is wrong and should
not be approved.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
                   ` (4 preceding siblings ...)
  2024-03-20 10:07 ` redi at gcc dot gnu.org
@ 2024-03-20 11:02 ` redi at gcc dot gnu.org
  2024-03-23 11:09 ` cvs-commit at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: redi at gcc dot gnu.org @ 2024-03-20 11:02 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> ---
Alternatively:

--- a/libstdc++-v3/include/std/string_view
+++ b/libstdc++-v3/include/std/string_view
@@ -602,15 +602,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // deduction and the other argument gets implicitly converted to the deduced
   // type (see N3766).

+#if __cpp_lib_three_way_comparison
   template<typename _CharT, typename _Traits>
     [[nodiscard]]
     constexpr bool
     operator==(basic_string_view<_CharT, _Traits> __x,
-               __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
+              type_identity_t<basic_string_view<_CharT, _Traits>> __y)
     noexcept
     { return __x.size() == __y.size() && __x.compare(__y) == 0; }

-#if __cpp_lib_three_way_comparison
   template<typename _CharT, typename _Traits>
     [[nodiscard]]
     constexpr auto
@@ -620,7 +620,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0))
     { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); }
 #else
-  template<typename _CharT, typename _Traits>
+  template<typena  template<typename _CharT, typename _Traits>
+    [[nodiscard]]
+    constexpr bool
+    operator==(basic_string_view<_CharT, _Traits> __x,
+              __type_identity_t<basic_string_view<_CharT, _Traits>> __y)
+    noexcept
+    { return __x.size() == __y.size() && __x.compare(__y) == 0; }
+
+me _CharT, typename _Traits>
     [[nodiscard]]
     constexpr bool
     operator==(basic_string_view<_CharT, _Traits> __x,


Our other uses of __type_identity_t (e.g. in container constructors) are
probably OK. Users can't overload those, and the exact signatures of member
functions are unspecified anyway (we can add/remove default arguments).

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [Bug libstdc++/114400] The resolution of LWG3950 seems incorrectly implemented
  2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
                   ` (5 preceding siblings ...)
  2024-03-20 11:02 ` redi at gcc dot gnu.org
@ 2024-03-23 11:09 ` cvs-commit at gcc dot gnu.org
  6 siblings, 0 replies; 8+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2024-03-23 11:09 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>:

https://gcc.gnu.org/g:f4605c53ea2eeafc13e14dd1ad00a0caf80057e2

commit r14-9642-gf4605c53ea2eeafc13e14dd1ad00a0caf80057e2
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Mar 20 11:07:56 2024 +0000

    libstdc++: Use std::type_identity_t in <string_view> as per LWG 3950
[PR114400]

    The difference between __type_identity_t and std::type_identity_t is
    observable, as demonstrated in the PR. Nobody in LWG seems to think this
    an example we should really care about, but it seems easy and harmless
    to change this.

    libstdc++-v3/ChangeLog:

            PR libstdc++/114400
            * include/std/string_view (operator==): Use std::type_identity_t
            in C++20 instead of our own __type_identity_t.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-03-23 11:09 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-20  2:57 [Bug libstdc++/114400] New: The resolution of LWG3950 seems incorrectly implemented de34 at live dot cn
2024-03-20  9:09 ` [Bug libstdc++/114400] " redi at gcc dot gnu.org
2024-03-20  9:16 ` redi at gcc dot gnu.org
2024-03-20  9:18 ` redi at gcc dot gnu.org
2024-03-20 10:02 ` de34 at live dot cn
2024-03-20 10:07 ` redi at gcc dot gnu.org
2024-03-20 11:02 ` redi at gcc dot gnu.org
2024-03-23 11:09 ` cvs-commit at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).