Phi
pointer_traits.hpp
1 #ifndef INCG_PHI_CORE_POINTER_TRAITS_HPP
2 #define INCG_PHI_CORE_POINTER_TRAITS_HPP
3 
4 #include "phi/phi_config.hpp"
5 
6 #if PHI_HAS_EXTENSION_PRAGMA_ONCE()
7 # pragma once
8 #endif
9 
10 #include "phi/compiler_support/constexpr.hpp"
11 #include "phi/compiler_support/noexcept.hpp"
12 #include "phi/compiler_support/warning.hpp"
13 #include "phi/core/address_of.hpp"
14 #include "phi/core/ptrdiff_t.hpp"
15 #include "phi/type_traits/conditional.hpp"
16 #include "phi/type_traits/detail/nat.hpp"
17 #include "phi/type_traits/has_difference_type.hpp"
18 #include "phi/type_traits/has_element_type.hpp"
19 #include "phi/type_traits/integral_constant.hpp"
20 #include "phi/type_traits/is_void.hpp"
21 
22 DETAIL_PHI_BEGIN_NAMESPACE()
23 
24 namespace detail
25 {
26  template <typename PointerT, bool = has_element_type<PointerT>::value>
28 
29  template <typename PointerT>
30  struct pointer_traits_element_type<PointerT, true>
31  {
32  using type = typename PointerT::element_type;
33  };
34 
35  template <template <typename, typename...> typename FancyPointerT, typename TypeT,
36  typename... ArgsT>
37  struct pointer_traits_element_type<FancyPointerT<TypeT, ArgsT...>, true>
38  {
39  using type = typename FancyPointerT<TypeT, ArgsT...>::element_type;
40  };
41 
42  template <template <typename, typename...> typename FancyPointerT, typename TypeT,
43  typename... ArgsT>
44  struct pointer_traits_element_type<FancyPointerT<TypeT, ArgsT...>, false>
45  {
46  using type = TypeT;
47  };
48 
49  template <typename PointerT, bool = has_difference_type<PointerT>::value>
51  {
52  using type = ptrdiff_t;
53  };
54 
55  template <typename PointerT>
56  struct pointer_traits_difference_type<PointerT, true>
57  {
58  using type = typename PointerT::difference_type;
59  };
60 
61  template <typename TypeT, typename OtherT>
62  struct has_rebind
63  {
64  private:
65  template <typename Type2T>
66  static false_type test(...);
67 
68  template <typename Type2T>
69  static true_type test(typename Type2T::template rebind<OtherT>* = 0);
70 
71  public:
72  PHI_CLANG_SUPPRESS_WARNING_WITH_PUSH("-Wzero-as-null-pointer-constant")
73 
74  static PHI_CONSTEXPR_AND_CONST bool value = decltype(test<TypeT>(0))::value;
75 
76  PHI_CLANG_SUPPRESS_WARNING_POP()
77  };
78 
79  template <typename TypeT, typename OtherT, bool = has_rebind<TypeT, OtherT>::value>
81  {
82 #if PHI_CPP_STANDARD_IS_ATLEAST(11)
83  using type = typename TypeT::template rebind<OtherT>;
84 #else
85  using type = typename TypeT::template rebind<OtherT>::other;
86 #endif
87  };
88 
89  template <template <typename, typename...> typename FancyPointerT, typename TypeT,
90  typename... ArgsT, typename OtherT>
91  struct pointer_traits_rebind<FancyPointerT<TypeT, ArgsT...>, OtherT, true>
92  {
93 #if PHI_CPP_STANDARD_IS_ATLEAST(11)
94  using type = typename FancyPointerT<TypeT, ArgsT...>::template rebind<OtherT>;
95 #else
96  using type = typename FancyPointerT<TypeT, ArgsT...>::template rebind<OtherT>::other;
97 #endif
98  };
99 
100  template <template <typename, typename...> typename FancyPointerT, typename TypeT,
101  typename... ArgsT, typename OtherT>
102  struct pointer_traits_rebind<FancyPointerT<TypeT, ArgsT...>, OtherT, false>
103  {
104  using type = FancyPointerT<OtherT, ArgsT...>;
105  };
106 } // namespace detail
107 
108 template <typename PointerT>
110 {
112  using pointer = PointerT;
113  using difference_type = typename detail::pointer_traits_difference_type<pointer>::type;
114  using element_type = typename detail::pointer_traits_element_type<pointer>::type;
115 
116 #if PHI_CPP_STANDARD_IS_ATLEAST(11)
117  template <typename OtherT>
118  using rebind = typename detail::pointer_traits_rebind<pointer, OtherT>::type;
119 #else
120  template <typename OtherT>
121  struct rebind
122  {
123  using other = typename detail::pointer_traits_rebind<pointer, OtherT>::type;
124  };
125 #endif
126 
127 public:
128  static PHI_CONSTEXPR pointer
129  pointer_to(conditional_t<is_void<element_type>::value, nat, element_type>& ptr) PHI_NOEXCEPT
130  {
131  return pointer::pointer_to(ptr);
132  }
133 };
134 
135 template <typename TypeT>
136 struct pointer_traits<TypeT*>
137 {
139  using pointer = TypeT*;
140  using difference_type = ptrdiff_t;
141  using element_type = TypeT;
142 
143 #if PHI_CPP_STANDARD_IS_ATLEAST(11)
144  template <typename OtherT>
145  using rebind = OtherT*;
146 #else
147  template <typename OtherT>
148  struct rebind
149  {
150  using other = OtherT*;
151  };
152 #endif
153 
154 public:
155  static PHI_CONSTEXPR pointer
156  pointer_to(conditional_t<is_void<element_type>::value, nat, element_type>& ptr) PHI_NOEXCEPT
157  {
158  return address_of(ptr);
159  }
160 };
161 
162 #if PHI_CPP_STANDARD_IS_ATLEAST(11)
163 
164 template <typename FromT, typename ToT>
165 using rebind_pointer_t = typename pointer_traits<FromT>::template rebind<ToT>;
166 
167 #else
168 
169 template <typename FromT, typename ToT>
170 using rebind_pointer_t = typename pointer_traits<FromT>::template rebind<ToT>::other;
171 
172 #endif
173 
174 DETAIL_PHI_END_NAMESPACE()
175 
176 #endif // INCG_PHI_CORE_POINTER_TRAITS_HPP
Definition: integral_constant.hpp:19
Definition: pointer_traits.hpp:27
Definition: pointer_traits.hpp:80
Definition: test_macros.hpp:18
Definition: nat.hpp:12
Definition: pointer_traits.hpp:121
Definition: pointer_traits.hpp:136
Definition: swap.hpp:23
Definition: pointer_traits.hpp:109
Definition: pointer_traits.hpp:62
Definition: is_void.hpp:17
Definition: pointer_traits.hpp:50