public inbox for libstdc++-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jonathan Wakely <redi@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org
Subject: [gcc r13-2884] libstdc++: Update std::pointer_traits to match new LWG 3545 wording
Date: Mon, 26 Sep 2022 22:48:30 +0000 (GMT)	[thread overview]
Message-ID: <20220926224831.001A0385840C@sourceware.org> (raw)

https://gcc.gnu.org/g:03cb9ed8dd603dbb77762ca948fc6381ba190731

commit r13-2884-g03cb9ed8dd603dbb77762ca948fc6381ba190731
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Sep 26 18:59:45 2022 +0100

    libstdc++: Update std::pointer_traits to match new LWG 3545 wording
    
    It was pointed out in recent LWG 3545 discussion that having a
    constrained partial specialization of std::pointer_traits can cause
    ambiguities with program-defined specializations. For example, the
    addition to the testcase has:
    
    template<typename P> requires std::derived_from<P, base_type
    struct std::pointer_traits<P>;
    
    This would be ambiguous with the library's own constrained partial
    specialization:
    
    template<typename Ptr> requires requires { typename Ptr::element_type; }
    struct std::pointer_traits<Ptr>;
    
    Neither specialization is more specialized than the other for a type
    that is derived from base_type and also has an element_type member.
    
    The solution is to remove the library's partial specialization, and do
    the check for Ptr::element_type in the __ptr_traits_elem helper (which
    is what we already do for !__cpp_concepts anyway).
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/ptr_traits.h (__ptr_traits_elem) [__cpp_concepts]:
            Also define the __ptr_traits_elem class template for the
            concepts case.
            (pointer_traits<Ptr>): Remove constrained partial
            specialization.
            * testsuite/20_util/pointer_traits/lwg3545.cc: Check for
            ambiguitiy with program-defined partial specialization.

Diff:
---
 libstdc++-v3/include/bits/ptr_traits.h               | 20 ++++++--------------
 .../testsuite/20_util/pointer_traits/lwg3545.cc      | 17 +++++++++++++++++
 2 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h
index ae8810706ab..71370ff4fc9 100644
--- a/libstdc++-v3/include/bits/ptr_traits.h
+++ b/libstdc++-v3/include/bits/ptr_traits.h
@@ -73,25 +73,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up>
     { using type = _SomeTemplate<_Up, _Types...>; };
 
-#if __cpp_concepts
-  // When concepts are supported detection of _Ptr::element_type is done
-  // by a requires-clause, so __ptr_traits_elem_t only needs to do this:
-  template<typename _Ptr>
-    using __ptr_traits_elem_t = typename __get_first_arg<_Ptr>::type;
-#else
   // Detect the element type of a pointer-like type.
   template<typename _Ptr, typename = void>
     struct __ptr_traits_elem : __get_first_arg<_Ptr>
     { };
 
   // Use _Ptr::element_type if is a valid type.
+#if __cpp_concepts
+  template<typename _Ptr> requires requires { typename _Ptr::element_type; }
+    struct __ptr_traits_elem<_Ptr, void>
+    { using type = typename _Ptr::element_type; };
+#else
   template<typename _Ptr>
     struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>>
     { using type = typename _Ptr::element_type; };
+#endif
 
   template<typename _Ptr>
     using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type;
-#endif
 
   /// @endcond
 
@@ -182,13 +181,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>>
     { };
 
-#if __cpp_concepts
-  template<typename _Ptr> requires requires { typename _Ptr::element_type; }
-    struct pointer_traits<_Ptr>
-    : __ptr_traits_impl<_Ptr, typename _Ptr::element_type>
-    { };
-#endif
-
   /**
    * @brief  Partial specialization for built-in pointers.
    * @headerfile memory
diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc
index 08c3ed01b75..93c64a353bd 100644
--- a/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc
+++ b/libstdc++-v3/testsuite/20_util/pointer_traits/lwg3545.cc
@@ -99,3 +99,20 @@ static_assert( is_same<pointer<Ctraits>, clever_ptr<char>>::value, "" );
 static_assert( is_same<difference_type<Ctraits>, std::ptrdiff_t>::value, "" );
 static_assert( is_same<rebind<Ctraits>, clever_ptr<short>>::value, "" );
 static_assert( is_same<pointer_to<Ctraits>, clever_ptr<char>>::value, "" );
+
+#ifdef __cpp_concepts
+struct ptr_base { };
+
+// Program-defined specialization must not be ambiguous with primary template.
+template<typename P> requires std::derived_from<P, ptr_base>
+struct std::pointer_traits<P>
+{
+  using element_type = int;
+  using difference_type = long;
+  using pointer = P;
+};
+
+struct Ptr : ptr_base { using element_type = int; };
+
+using E = std::pointer_traits<Ptr>::element_type;
+#endif

                 reply	other threads:[~2022-09-26 22:48 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220926224831.001A0385840C@sourceware.org \
    --to=redi@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    --cc=libstdc++-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).