Skip to content

Commit 650b451

Browse files
authored
[libc++] Simplify the implementation of pointer_traits a bit (#142260)
1 parent 52ff58c commit 650b451

File tree

1 file changed

+33
-83
lines changed

1 file changed

+33
-83
lines changed

libcxx/include/__memory/pointer_traits.h

Lines changed: 33 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
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>
2021
#include <__type_traits/integral_constant.h>
2122
#include <__type_traits/is_class.h>
2223
#include <__type_traits/is_function.h>
2324
#include <__type_traits/is_void.h>
25+
#include <__type_traits/nat.h>
2426
#include <__type_traits/void_t.h>
2527
#include <__utility/declval.h>
2628
#include <__utility/forward.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-
};
40+
struct __pointer_traits_element_type_impl {};
5541

5642
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-
};
60-
61-
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 _LIBCPP_NODEBUG = 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,40 +212,35 @@ template <class _Tp>
257212
struct __pointer_of {};
258213

259214
template <class _Tp>
260-
requires(__has_pointer<_Tp>::value)
215+
concept __has_pointer_member = requires { typename _Tp::pointer; };
216+
217+
template <class _Tp>
218+
concept __has_element_type_member = requires { typename _Tp::element_type; };
219+
220+
template <class _Tp>
221+
requires __has_pointer_member<_Tp>
261222
struct __pointer_of<_Tp> {
262223
using type _LIBCPP_NODEBUG = typename _Tp::pointer;
263224
};
264225

265226
template <class _Tp>
266-
requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value)
227+
requires(!__has_pointer_member<_Tp> && __has_element_type_member<_Tp>)
267228
struct __pointer_of<_Tp> {
268229
using type _LIBCPP_NODEBUG = typename _Tp::element_type*;
269230
};
270231

271232
template <class _Tp>
272-
requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value &&
273-
__has_element_type<pointer_traits<_Tp>>::value)
233+
requires(!__has_pointer_member<_Tp> && !__has_element_type_member<_Tp> &&
234+
__has_element_type_member<pointer_traits<_Tp>>)
274235
struct __pointer_of<_Tp> {
275236
using type _LIBCPP_NODEBUG = typename pointer_traits<_Tp>::element_type*;
276237
};
277238

278239
template <typename _Tp>
279240
using __pointer_of_t _LIBCPP_NODEBUG = typename __pointer_of<_Tp>::type;
280241

281-
template <class _Tp, class _Up>
282-
struct __pointer_of_or {
283-
using type _LIBCPP_NODEBUG = _Up;
284-
};
285-
286-
template <class _Tp, class _Up>
287-
requires requires { typename __pointer_of_t<_Tp>; }
288-
struct __pointer_of_or<_Tp, _Up> {
289-
using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>;
290-
};
291-
292242
template <typename _Tp, typename _Up>
293-
using __pointer_of_or_t _LIBCPP_NODEBUG = typename __pointer_of_or<_Tp, _Up>::type;
243+
using __pointer_of_or_t _LIBCPP_NODEBUG = __detected_or_t<_Up, __pointer_of_t, _Tp>;
294244

295245
template <class _Smart>
296246
concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); };

0 commit comments

Comments
 (0)