[libcxx-commits] [libcxx] 078651b - [libc++] Implement LWG3545: std::pointer_traits should be SFINAE-friendly. (#65177)

via libcxx-commits libcxx-commits at lists.llvm.org
Mon Sep 18 05:47:03 PDT 2023


Author: Daniel Cheng
Date: 2023-09-18T08:46:59-04:00
New Revision: 078651b6de4b767b91e3e6a51e5df11a06d7bc4f

URL: https://github.com/llvm/llvm-project/commit/078651b6de4b767b91e3e6a51e5df11a06d7bc4f
DIFF: https://github.com/llvm/llvm-project/commit/078651b6de4b767b91e3e6a51e5df11a06d7bc4f.diff

LOG: [libc++] Implement LWG3545: std::pointer_traits should be SFINAE-friendly. (#65177)

See https://wg21.link/LWG3545 for background and details.

Differential Revision: https://reviews.llvm.org/D158922

Added: 
    libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp
    libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx23Issues.csv
    libcxx/include/__memory/pointer_traits.h

Removed: 
    libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp
    libcxx/test/std/utilities/memory/pointer.traits/difference_type.pass.cpp
    libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp
    libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp
    libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp


################################################################################
diff  --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 9015084d33cf4f8..20b0fa7fc9d1fcd 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -190,7 +190,7 @@
 "`3118 <https://wg21.link/LWG3118>`__","``fpos`` equality comparison unspecified", "November 2022","","",""
 "`3177 <https://wg21.link/LWG3177>`__","Limit permission to specialize variable templates to program-defined types", "November 2022","|Nothing to do|","",""
 "`3515 <https://wg21.link/LWG3515>`__","§[stacktrace.basic.nonmem]: ``operator<<`` should be less templatized", "November 2022","","",""
-"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","","",""
+"`3545 <https://wg21.link/LWG3545>`__","``std::pointer_traits`` should be SFINAE-friendly", "November 2022","|Complete|","18.0",""
 "`3569 <https://wg21.link/LWG3569>`__","``join_view`` fails to support ranges of ranges with non-default_initializable iterators", "November 2022","","","|ranges|"
 "`3594 <https://wg21.link/LWG3594>`__","``inout_ptr`` — inconsistent ``release()`` in destructor", "November 2022","","",""
 "`3597 <https://wg21.link/LWG3597>`__","Unsigned integer types don't model advanceable", "November 2022","","","|ranges|"

diff  --git a/libcxx/include/__memory/pointer_traits.h b/libcxx/include/__memory/pointer_traits.h
index c33e7bd43f29f7d..7617948ed76bd66 100644
--- a/libcxx/include/__memory/pointer_traits.h
+++ b/libcxx/include/__memory/pointer_traits.h
@@ -35,7 +35,7 @@ template <class _Tp>
 struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {};
 
 template <class _Ptr, bool = __has_element_type<_Ptr>::value>
-struct __pointer_traits_element_type;
+struct __pointer_traits_element_type {};
 
 template <class _Ptr>
 struct __pointer_traits_element_type<_Ptr, true>
@@ -111,12 +111,14 @@ struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
     typedef _Sp<_Up, _Args...> type;
 };
 
+template <class _Ptr, class = void>
+struct __pointer_traits_impl {};
+
 template <class _Ptr>
-struct _LIBCPP_TEMPLATE_VIS pointer_traits
-{
-    typedef _Ptr                                                     pointer;
-    typedef typename __pointer_traits_element_type<pointer>::type    element_type;
-    typedef typename __pointer_traits_
diff erence_type<pointer>::type 
diff erence_type;
+struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {
+  typedef _Ptr pointer;
+  typedef typename __pointer_traits_element_type<pointer>::type element_type;
+  typedef typename __pointer_traits_
diff erence_type<pointer>::type 
diff erence_type;
 
 #ifndef _LIBCPP_CXX03_LANG
     template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
@@ -133,6 +135,9 @@ struct _LIBCPP_TEMPLATE_VIS pointer_traits
         {return pointer::pointer_to(__r);}
 };
 
+template <class _Ptr>
+struct _LIBCPP_TEMPLATE_VIS pointer_traits : __pointer_traits_impl<_Ptr> {};
+
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*>
 {

diff  --git a/libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp b/libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp
deleted file mode 100644
index 37c5ad9610a60cb..000000000000000
--- a/libcxx/test/libcxx/iterators/iterator.requirements/iterator.concepts/iterator.concept.random.access/contiguous_iterator.verify.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
-// This test checks that std::contiguous_iterator uses std::to_address, which is not SFINAE-friendly
-// when the type is missing the `T::element_type` typedef.
-
-#include <iterator>
-
-#include <compare>
-#include <cstddef>
-
-struct no_element_type {
-    typedef std::contiguous_iterator_tag    iterator_category;
-    typedef int                             value_type;
-    typedef std::ptr
diff _t                  
diff erence_type;
-    typedef int*                            pointer;
-    typedef int&                            reference;
-    typedef no_element_type                 self;
-
-    no_element_type();
-
-    reference operator*() const;
-    pointer operator->() const;
-    auto operator<=>(const self&) const = default;
-
-    self& operator++();
-    self operator++(int);
-
-    self& operator--();
-    self operator--(int);
-
-    self& operator+=(
diff erence_type n);
-    self operator+(
diff erence_type n) const;
-    friend self operator+(
diff erence_type n, self x);
-
-    self& operator-=(
diff erence_type n);
-    self operator-(
diff erence_type n) const;
-    
diff erence_type operator-(const self& n) const;
-
-    reference operator[](
diff erence_type n) const;
-};
-
-void test() {
-    (void) std::contiguous_iterator<no_element_type>;
-        // expected-error@*:* {{implicit instantiation of undefined template}}
-        // expected-note@*:* {{to_address}}
-}

diff  --git a/libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp
new file mode 100644
index 000000000000000..4d05c10e0fbdc95
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/pointer.conversion/to_address_without_pointer_traits.pass.cpp
@@ -0,0 +1,66 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// template <class Ptr> constexpr auto to_address(const Ptr& p) noexcept;
+//     Should not require a specialization of pointer_traits for Ptr.
+
+#include <memory>
+#include <type_traits>
+#include <utility>
+
+struct IntPtr {
+  constexpr int* operator->() const { return ptr; }
+
+  int* ptr;
+};
+
+template <class T, bool>
+struct TemplatedPtr {
+  constexpr T* operator->() const { return ptr; }
+
+  T* ptr;
+};
+
+template <template <class...> class Templ, class Ignore, class... Args>
+struct is_valid_expansion_impl : std::false_type {};
+
+template <template <class...> class Templ, class... Args>
+struct is_valid_expansion_impl<Templ, decltype((void)Templ<Args...>{}, 0), Args...> : std::true_type {};
+
+template <template <class...> class Templ, class... Args>
+using is_valid_expansion = is_valid_expansion_impl<Templ, int, Args...>;
+
+template <class Ptr>
+using TestToAddressCall = decltype(std::to_address(std::declval<Ptr>()));
+
+constexpr bool test() {
+  int i = 0;
+
+  static_assert(std::to_address(IntPtr{nullptr}) == nullptr);
+  static_assert(std::to_address(IntPtr{&i}) == &i);
+
+  bool b = false;
+
+  static_assert(std::to_address(TemplatedPtr<bool, true>{nullptr}) == nullptr);
+  static_assert(std::to_address(TemplatedPtr<bool, true>{&b}) == &b);
+
+  static_assert(!is_valid_expansion<TestToAddressCall, int>::value);
+  static_assert(is_valid_expansion<TestToAddressCall, IntPtr>::value);
+  static_assert(is_valid_expansion<TestToAddressCall, TemplatedPtr<bool, true>>::value);
+
+  return true;
+}
+
+int main(int, char**) {
+  static_assert(test());
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/memory/pointer.traits/
diff erence_type.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/
diff erence_type.pass.cpp
deleted file mode 100644
index 7546df902882065..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/
diff erence_type.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class T>
-// struct pointer_traits<T*>
-// {
-//     typedef ptr
diff _t 
diff erence_type;
-//     ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    static_assert((std::is_same<std::pointer_traits<double*>::
diff erence_type, std::ptr
diff _t>::value), "");
-
-  return 0;
-}

diff  --git a/libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp
deleted file mode 100644
index e4f11c28e29be6b..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/element_type.pass.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class T>
-// struct pointer_traits<T*>
-// {
-//     typedef T element_type;
-//     ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
-    static_assert((std::is_same<std::pointer_traits<const short*>::element_type, const short>::value), "");
-
-  return 0;
-}

diff  --git a/libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp
deleted file mode 100644
index 14054b3c4f65bc4..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/pointer.pass.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class Ptr>
-// struct pointer_traits
-// {
-//     typedef Ptr pointer;
-//     ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-struct A
-{
-    typedef short element_type;
-    typedef char 
diff erence_type;
-};
-
-int main(int, char**)
-{
-    static_assert((std::is_same<std::pointer_traits<A>::pointer, A>::value), "");
-    static_assert((std::is_same<std::pointer_traits<int*>::pointer, int*>::value), "");
-
-  return 0;
-}

diff  --git a/libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp
deleted file mode 100644
index f64213c9b887ceb..000000000000000
--- a/libcxx/test/std/utilities/memory/pointer.traits/rebind.pass.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// <memory>
-
-// template <class T>
-// struct pointer_traits<T*>
-// {
-//     template <class U> using rebind = U*;
-//     ...
-// };
-
-#include <memory>
-#include <type_traits>
-
-#include "test_macros.h"
-
-int main(int, char**)
-{
-#if TEST_STD_VER >= 11
-    static_assert((std::is_same<std::pointer_traits<int*>::rebind<double>, double*>::value), "");
-#else
-    static_assert((std::is_same<std::pointer_traits<int*>::rebind<double>::other, double*>::value), "");
-#endif
-
-  return 0;
-}

diff  --git a/libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp b/libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp
new file mode 100644
index 000000000000000..19461508ca0f328
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/pointer.traits/types.compile.pass.cpp
@@ -0,0 +1,289 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <memory>
+
+// template <class Ptr>
+// struct pointer_traits
+// {
+//     <details>
+// };
+//
+// template <class T>
+// struct pointer_traits<T*>
+// {
+//     using pointer = T*;
+//     using element_type = T;
+//     using 
diff erence_type = ptr
diff _t;
+//     template <class U> using rebind = U*;
+//     static constexpr pointer pointer_to(<details>) noexcept;
+//     ...
+// };
+
+#include <memory>
+#include <type_traits>
+
+#include "test_macros.h"
+
+template <typename... Ts>
+struct VoidifyImpl {
+  using type = void;
+};
+
+template <typename... Ts>
+using Voidify = typename VoidifyImpl<Ts...>::type;
+
+template <class T, class = void>
+struct HasElementType : std::false_type {};
+
+template <class T>
+struct HasElementType<T, Voidify<typename std::pointer_traits<T>::element_type> > : std::true_type {};
+
+template <class T, class = void>
+struct HasPointerType : std::false_type {};
+
+template <class T>
+struct HasPointerType<T, Voidify<typename std::pointer_traits<T>::pointer> > : std::true_type {};
+
+template <class T, class = void>
+struct HasDifferenceType : std::false_type {};
+
+template <class T>
+struct HasDifferenceType<T, Voidify<typename std::pointer_traits<T>::
diff erence_type> > : std::true_type {};
+
+template <class T, class U, class = void>
+struct HasRebind : std::false_type {};
+
+template <class T, class U>
+struct HasRebind<T, U, Voidify<typename std::pointer_traits<T>::template rebind<U> > > : std::true_type {};
+
+template <class T, class = void>
+struct HasPointerTo : std::false_type {};
+
+template <class T>
+struct HasPointerTo<
+    T,
+    Voidify<decltype(std::pointer_traits<T>::pointer_to(
+        std::declval<typename std::add_lvalue_reference<typename std::pointer_traits<T>::element_type>::type>()))> >
+    : std::true_type {};
+
+struct Irrelevant;
+
+struct NotAPtr {};
+
+struct LongPtr {};
+
+int global_int;
+
+template <class T, class Arg>
+struct TemplatedPtr;
+
+struct PtrWithElementType {
+  using element_type = int;
+  template <class U>
+#if TEST_STD_VER >= 11
+  using rebind = TemplatedPtr<U, Irrelevant>;
+#else
+  struct rebind {
+    using other = TemplatedPtr<U, Irrelevant>;
+  };
+#endif
+  static TEST_CONSTEXPR_CXX14 PtrWithElementType pointer_to(element_type&) { return {&global_int}; }
+  int* ptr;
+};
+
+template <class T, class Arg>
+struct TemplatedPtr {
+  template <class U, class = typename std::enable_if<std::is_same<long, U>::value>::type>
+#if TEST_STD_VER >= 11
+  using rebind = LongPtr;
+#else
+  struct rebind {
+    using other = LongPtr;
+  };
+#endif
+  static TEST_CONSTEXPR_CXX14 TemplatedPtr pointer_to(T&) { return {&global_int}; }
+
+  T* ptr;
+};
+
+template <class T, class Arg>
+struct TemplatedPtrWithElementType {
+  using element_type = int;
+#if TEST_STD_VER >= 11
+  template <class U, class = typename std::enable_if<std::is_same<long, U>::value>::type>
+  using rebind = LongPtr;
+#else
+  template <class U, class = typename std::enable_if<std::is_same<long, U>::value>::type>
+  struct rebind {
+    using other = LongPtr;
+  };
+#endif
+  static TEST_CONSTEXPR_CXX14 TemplatedPtrWithElementType pointer_to(element_type&) { return {&global_int}; }
+
+  element_type* ptr;
+};
+
+int main() {
+  {
+    using Ptr = NotAPtr;
+    static_assert(!HasElementType<Ptr>::value, "");
+    static_assert(!HasPointerType<Ptr>::value, "");
+    static_assert(!HasDifferenceType<Ptr>::value, "");
+    static_assert(!HasRebind<Ptr, long>::value, "");
+    static_assert(!HasPointerTo<Ptr>::value, "");
+  }
+
+  {
+    using Ptr = int*;
+
+    static_assert(HasElementType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+    static_assert(HasPointerType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+    static_assert(HasDifferenceType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::
diff erence_type, ptr
diff _t);
+
+    static_assert(HasRebind<Ptr, long>::value, "");
+#if TEST_STD_VER >= 11
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
+#else
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, long*);
+#endif
+
+    static_assert(HasPointerTo<Ptr>::value, "");
+    int variable = 0;
+    ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), Ptr);
+#if TEST_STD_VER >= 20
+    static_assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable, "");
+#endif
+  }
+
+  {
+    using Ptr = const int*;
+
+    static_assert(HasElementType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, const int);
+
+    static_assert(HasPointerType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+    static_assert(HasDifferenceType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::
diff erence_type, ptr
diff _t);
+
+    static_assert(HasRebind<Ptr, long>::value, "");
+#if TEST_STD_VER >= 11
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, long*);
+#else
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, long*);
+#endif
+
+    static_assert(HasPointerTo<Ptr>::value, "");
+    const int const_variable = 0;
+    ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(const_variable)), Ptr);
+#if TEST_STD_VER >= 20
+    static_assert(std::pointer_traits<Ptr>::pointer_to(const_variable) == &const_variable, "");
+#endif
+    int variable = 0;
+    ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(variable)), Ptr);
+#if TEST_STD_VER >= 20
+    static_assert(std::pointer_traits<Ptr>::pointer_to(variable) == &variable, "");
+#endif
+  }
+
+  {
+    using Ptr = PtrWithElementType;
+
+    static_assert(HasElementType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+    static_assert(HasPointerType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+    static_assert(HasDifferenceType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::
diff erence_type, ptr
diff _t);
+
+    static_assert(HasRebind<Ptr, long>::value, "");
+#if TEST_STD_VER >= 11
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, TemplatedPtr<long, Irrelevant>);
+#else
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, TemplatedPtr<long, Irrelevant>);
+#endif
+
+    static_assert(HasPointerTo<Ptr>::value, "");
+    int ignored = 0;
+    ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
+#if TEST_STD_VER >= 20
+    static_assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int, "");
+#endif
+  }
+
+  {
+    using Ptr = TemplatedPtr<int, Irrelevant>;
+
+    static_assert(HasElementType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+    static_assert(HasPointerType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+    static_assert(HasDifferenceType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::
diff erence_type, ptr
diff _t);
+
+    static_assert(HasRebind<Ptr, long>::value, "");
+    static_assert(HasRebind<Ptr, long long>::value, "");
+#if TEST_STD_VER >= 11
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtr<long long, Irrelevant>);
+#else
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, LongPtr);
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>::other, TemplatedPtr<long long, Irrelevant>);
+#endif
+
+    static_assert(HasPointerTo<Ptr>::value, "");
+    int ignored = 0;
+    ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
+#if TEST_STD_VER >= 20
+    static_assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int, "");
+#endif
+  }
+
+  {
+    using Ptr = TemplatedPtrWithElementType<Irrelevant, Irrelevant>;
+
+    static_assert(HasElementType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+    static_assert(HasPointerType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+    static_assert(HasDifferenceType<Ptr>::value, "");
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::
diff erence_type, ptr
diff _t);
+
+    static_assert(HasRebind<Ptr, long>::value, "");
+    static_assert(HasRebind<Ptr, long long>::value, "");
+#if TEST_STD_VER >= 11
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>, LongPtr);
+    ASSERT_SAME_TYPE(
+        typename std::pointer_traits<Ptr>::rebind<long long>, TemplatedPtrWithElementType<long long, Irrelevant>);
+#else
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long>::other, LongPtr);
+    ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::rebind<long long>::other,
+                     TemplatedPtrWithElementType<long long, Irrelevant>);
+#endif
+
+    static_assert(HasPointerTo<Ptr>::value, "");
+    int ignored = 0;
+    ASSERT_SAME_TYPE(decltype(std::pointer_traits<Ptr>::pointer_to(ignored)), Ptr);
+#if TEST_STD_VER >= 20
+    static_assert(std::pointer_traits<Ptr>::pointer_to(ignored).ptr == &global_int, "");
+#endif
+  }
+}


        


More information about the libcxx-commits mailing list