xref: /xnu-11215/libkern/os/cpp_util.h (revision 1031c584)
1 #ifndef _OS_CPP_UTIL_H
2 #define _OS_CPP_UTIL_H
3 
4 #include <sys/cdefs.h>
5 #include <sys/_types/_size_t.h>
6 
7 #if __has_feature(cxx_nullptr) && __has_feature(cxx_decltype)
8 # define OS_HAS_NULLPTR 1
9 #endif
10 
11 #if __has_feature(cxx_rvalue_references) || __has_extension(cxx_rvalue_references)
12 # define OS_HAS_RVALUE_REFERENCES 1
13 #endif
14 
15 #if (defined(__has_include) && __has_include(<__xnu_libcxx_sentinel.h>) && __has_include(<new>))
16 #include <new>
17 #else
18 void* operator new(size_t, void*) noexcept; // forward declaration needed for placement-new
19 #endif
20 
21 namespace os {
22 #if OS_HAS_NULLPTR
23 typedef decltype(nullptr) nullptr_t;
24 #endif
25 
26 /*
27  * Reference removal
28  */
29 
30 template <class _T> struct remove_reference       {typedef _T type;};
31 template <class _T> struct remove_reference<_T&>  {typedef _T type;};
32 template <class _T> struct remove_reference<_T &&> {typedef _T type;};
33 template <class _T> using remove_reference_t = typename remove_reference<_T>::type;
34 
35 /*
36  * Pointer removal
37  */
38 
39 template <class _T> struct remove_pointer                     {typedef _T type;};
40 template <class _T> struct remove_pointer<_T*>                {typedef _T type;};
41 template <class _T> struct remove_pointer<_T* const>          {typedef _T type;};
42 template <class _T> struct remove_pointer<_T* volatile>       {typedef _T type;};
43 template <class _T> struct remove_pointer<_T* const volatile> {typedef _T type;};
44 template <class _T> using remove_pointer_t = typename remove_pointer<_T>::type;
45 
46 /*
47  * Const removal
48  */
49 
50 template <class _T> struct remove_const           {typedef _T type;};
51 template <class _T> struct remove_const<const _T> {typedef _T type;};
52 template <class _T> using remove_const_t = typename remove_const<_T>::type;
53 
54 /*
55  * Volatile removal
56  */
57 
58 template <class _T> struct remove_volatile              {typedef _T type;};
59 template <class _T> struct remove_volatile<volatile _T> {typedef _T type;};
60 template <class _T> using remove_volatile_t = typename remove_volatile<_T>::type;
61 
62 /*
63  * Extent removal
64  */
65 
66 template<class _T> struct remove_extent { typedef _T type; };
67 template<class _T> struct remove_extent<_T[]> { typedef _T type; };
68 template<class _T, size_t N> struct remove_extent<_T[N]> { typedef _T type; };
69 template <class _T> using remove_extent_t = typename remove_extent<_T>::type;
70 
71 
72 template <class T> struct is_lvalue_reference { static constexpr bool value = false; };
73 template <class T> struct is_lvalue_reference<T&> { static constexpr bool value = true; };
74 
75 /*
76  * is_same
77  */
78 
79 template<class T, class U> struct is_same { static constexpr bool value = false; };
80 template<class T> struct is_same<T, T> { static constexpr bool value = true; };
81 
82 /*
83  * Move
84  */
85 
86 template <class _T>
87 inline typename remove_reference<_T>::type &&
88 move(_T && _t)
89 {
90 	typedef typename os::remove_reference<_T>::type _U;
91 	return static_cast<_U &&>(_t);
92 }
93 
94 template <class T>
95 T*
96 move(T* first, T* last, T* d_first)
97 {
98 	for (; first != last; ++d_first, (void)++first) {
99 		*d_first = os::move(*first);
100 	}
101 	return d_first;
102 }
103 
104 template <class T>
105 constexpr T && forward(os::remove_reference_t<T>&t) noexcept {
106 	return static_cast<T &&>(t);
107 }
108 
109 template <class T>
110 constexpr T && forward(os::remove_reference_t<T>&& t) noexcept {
111 	static_assert(!os::is_lvalue_reference<T>::value,
112 	    "can not forward an rvalue as an lvalue");
113 	return static_cast<T &&>(t);
114 }
115 
116 // Moves [first, last) into the range ending at d_last,
117 // proceeding backwards (from last to first)
118 // UB if d_last is within (first, last]
119 template <class T>
120 T*
121 move_backward(T* first, T* last, T* d_last)
122 {
123 	while (first != last) {
124 		*(--d_last) = os::move(*(--last));
125 	}
126 	return d_last;
127 }
128 
129 template <class T>
130 T*
131 uninitialized_move(T* first, T* last, T* d_first)
132 {
133 	for (; first != last; ++d_first, (void) ++first) {
134 		::new (static_cast<void*>(d_first)) T(os::move(*first));
135 	}
136 	return first;
137 }
138 
139 template <class T>
140 void
141 destroy(T* first, T* last)
142 {
143 	for (; first != last; ++first) {
144 		first->~T();
145 	}
146 }
147 
148 template <class T>
149 void
150 uninitialized_value_construct(T* first, T* last)
151 {
152 	for (; first != last; ++first) {
153 		::new (static_cast<void*>(first)) T();
154 	}
155 }
156 }
157 
158 #endif /* _OS_CPP_UTIL_H */
159