Skip to content

Commit 797de75

Browse files
committed
[libc++] Simplify the implementation of pointer_traits a bit
1 parent f1886b1 commit 797de75

File tree

1 file changed

+29
-71
lines changed

1 file changed

+29
-71
lines changed

libcxx/include/__memory/pointer_traits.h

Lines changed: 29 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@
1616
#include <__type_traits/conditional.h>
1717
#include <__type_traits/conjunction.h>
1818
#include <__type_traits/decay.h>
19+
#include <__type_traits/detected_or.h>
1920
#include <__type_traits/enable_if.h>
21+
#include <__type_traits/nat.h>
2022
#include <__type_traits/integral_constant.h>
2123
#include <__type_traits/is_class.h>
2224
#include <__type_traits/is_function.h>
@@ -34,87 +36,46 @@ _LIBCPP_PUSH_MACROS
3436

3537
_LIBCPP_BEGIN_NAMESPACE_STD
3638

37-
// clang-format off
38-
#define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \
39-
template <class _Tp, class = void> \
40-
struct NAME : false_type {}; \
41-
template <class _Tp> \
42-
struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {}
43-
// clang-format on
44-
45-
_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer);
46-
_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type);
47-
48-
template <class _Ptr, bool = __has_element_type<_Ptr>::value>
49-
struct __pointer_traits_element_type {};
50-
5139
template <class _Ptr>
52-
struct __pointer_traits_element_type<_Ptr, true> {
53-
using type _LIBCPP_NODEBUG = typename _Ptr::element_type;
54-
};
55-
56-
template <template <class, class...> class _Sp, class _Tp, class... _Args>
57-
struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true> {
58-
using type _LIBCPP_NODEBUG = typename _Sp<_Tp, _Args...>::element_type;
59-
};
40+
struct __pointer_traits_element_type_impl {};
6041

6142
template <template <class, class...> class _Sp, class _Tp, class... _Args>
62-
struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false> {
43+
struct __pointer_traits_element_type_impl<_Sp<_Tp, _Args...> > {
6344
using type _LIBCPP_NODEBUG = _Tp;
6445
};
6546

66-
template <class _Tp, class = void>
67-
struct __has_difference_type : false_type {};
68-
69-
template <class _Tp>
70-
struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {};
71-
72-
template <class _Ptr, bool = __has_difference_type<_Ptr>::value>
73-
struct __pointer_traits_difference_type {
74-
using type _LIBCPP_NODEBUG = ptrdiff_t;
75-
};
47+
template <class _Ptr, class = void>
48+
struct __pointer_traits_element_type : __pointer_traits_element_type_impl<_Ptr> {};
7649

7750
template <class _Ptr>
78-
struct __pointer_traits_difference_type<_Ptr, true> {
79-
using type _LIBCPP_NODEBUG = typename _Ptr::difference_type;
51+
struct __pointer_traits_element_type<_Ptr, __void_t<typename _Ptr::element_type>> {
52+
using type _LIBCPP_NODEBUG = typename _Ptr::element_type;
8053
};
8154

8255
template <class _Tp, class _Up>
83-
struct __has_rebind {
84-
private:
85-
template <class _Xp>
86-
static false_type __test(...);
87-
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
88-
template <class _Xp>
89-
static true_type __test(typename _Xp::template rebind<_Up>* = 0);
90-
_LIBCPP_SUPPRESS_DEPRECATED_POP
56+
struct __pointer_traits_rebind_impl {
57+
static_assert(false, "Cannot rebind pointer; did you forget to add a rebind member to your pointer?");
58+
};
9159

92-
public:
93-
static const bool value = decltype(__test<_Tp>(0))::value;
60+
template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
61+
struct __pointer_traits_rebind_impl<_Sp<_Tp, _Args...>, _Up> {
62+
using type _LIBCPP_NODEBUG = _Sp<_Up, _Args...>;
9463
};
9564

96-
template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value>
97-
struct __pointer_traits_rebind {
65+
template <class _Tp, class _Up, class = void>
66+
struct __pointer_traits_rebind : __pointer_traits_rebind_impl<_Tp, _Up> {};
67+
68+
template <class _Tp, class _Up>
69+
struct __pointer_traits_rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up> > > {
9870
#ifndef _LIBCPP_CXX03_LANG
9971
using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>;
10072
#else
10173
using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other;
10274
#endif
10375
};
10476

105-
template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
106-
struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true> {
107-
#ifndef _LIBCPP_CXX03_LANG
108-
using type _LIBCPP_NODEBUG = typename _Sp<_Tp, _Args...>::template rebind<_Up>;
109-
#else
110-
using type _LIBCPP_NODEBUG = typename _Sp<_Tp, _Args...>::template rebind<_Up>::other;
111-
#endif
112-
};
113-
114-
template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
115-
struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false> {
116-
typedef _Sp<_Up, _Args...> type;
117-
};
77+
template <class _Tp>
78+
using __difference_type_member = typename _Tp::difference_type;
11879

11980
template <class _Ptr, class = void>
12081
struct __pointer_traits_impl {};
@@ -123,7 +84,7 @@ template <class _Ptr>
12384
struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {
12485
typedef _Ptr pointer;
12586
typedef typename __pointer_traits_element_type<pointer>::type element_type;
126-
typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
87+
using difference_type = __detected_or_t<ptrdiff_t, __difference_type_member, pointer>;
12788

12889
#ifndef _LIBCPP_CXX03_LANG
12990
template <class _Up>
@@ -135,9 +96,6 @@ struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_ty
13596
};
13697
#endif // _LIBCPP_CXX03_LANG
13798

138-
private:
139-
struct __nat {};
140-
14199
public:
142100
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
143101
pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) {
@@ -164,9 +122,6 @@ struct pointer_traits<_Tp*> {
164122
};
165123
#endif
166124

167-
private:
168-
struct __nat {};
169-
170125
public:
171126
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
172127
pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT {
@@ -257,20 +212,23 @@ template <class _Tp>
257212
struct __pointer_of {};
258213

259214
template <class _Tp>
260-
requires(__has_pointer<_Tp>::value)
215+
concept __use_pointer_member = requires { typename _Tp::pointer; };
216+
217+
template <__use_pointer_member _Tp>
261218
struct __pointer_of<_Tp> {
262219
using type _LIBCPP_NODEBUG = typename _Tp::pointer;
263220
};
264221

265222
template <class _Tp>
266-
requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value)
223+
concept __use_element_type_member = !__use_pointer_member<_Tp> && requires { typename _Tp::element_type; };
224+
225+
template <__use_element_type_member _Tp>
267226
struct __pointer_of<_Tp> {
268227
using type _LIBCPP_NODEBUG = typename _Tp::element_type*;
269228
};
270229

271230
template <class _Tp>
272-
requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value &&
273-
__has_element_type<pointer_traits<_Tp>>::value)
231+
requires(!__use_element_type_member<_Tp>)
274232
struct __pointer_of<_Tp> {
275233
using type _LIBCPP_NODEBUG = typename pointer_traits<_Tp>::element_type*;
276234
};

0 commit comments

Comments
 (0)