[libcxx-commits] [libcxx] [libc++] Implement LWG3545: std::pointer_traits should be SFINAE-friendly. (PR #65177)
Daniel Cheng via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 14 17:35:36 PDT 2023
================
@@ -0,0 +1,325 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 difference_type = ptrdiff_t;
+// template <class U> using rebind = U*;
+// static constexpr pointer pointer_to(<details>) noexcept;
+// ...
+// };
+
+#include <memory>
+#include <cassert>
+#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>::difference_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;
+
+#if TEST_STD_VER >= 11
+# define CONSTEXPR_IF_SUPPORTED constexpr
+#else
+# define CONSTEXPR_IF_SUPPORTED
+#endif
+
+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 CONSTEXPR_IF_SUPPORTED 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 CONSTEXPR_IF_SUPPORTED 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 CONSTEXPR_IF_SUPPORTED TemplatedPtrWithElementType pointer_to(element_type&) { return {&global_int}; }
+
+ element_type* ptr;
+};
+
+#if TEST_STD_VER >= 14
+constexpr
+#endif
+ bool
+ test() {
+ {
+ using Ptr = NotAPtr;
+ assert(!HasElementType<Ptr>::value);
+ assert(!HasPointerType<Ptr>::value);
+ assert(!HasDifferenceType<Ptr>::value);
+ assert((!HasRebind<Ptr, long>::value));
+ assert(!HasPointerTo<Ptr>::value);
+ }
+
+ {
+ using Ptr = int*;
+
+ assert(HasElementType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::element_type, int);
+
+ assert(HasPointerType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::pointer, Ptr);
+
+ assert(HasDifferenceType<Ptr>::value);
+ ASSERT_SAME_TYPE(typename std::pointer_traits<Ptr>::difference_type, ptrdiff_t);
+
+ assert((HasRebind<Ptr, long>::value));
----------------
zetafunction wrote:
Done.
https://github.com/llvm/llvm-project/pull/65177
More information about the libcxx-commits
mailing list