]> git.saurik.com Git - apple/xnu.git/blob - libkern/os/cpp_util.h
xnu-7195.101.1.tar.gz
[apple/xnu.git] / libkern / os / cpp_util.h
1 #ifndef _OS_CPP_UTIL_H
2 #define _OS_CPP_UTIL_H
3
4 #include <sys/cdefs.h>
5
6 #if __has_feature(cxx_nullptr) && __has_feature(cxx_decltype)
7 # define OS_HAS_NULLPTR 1
8 #endif
9
10 #if __has_feature(cxx_rvalue_references) || __has_extension(cxx_rvalue_references)
11 # define OS_HAS_RVALUE_REFERENCES 1
12 #endif
13
14 void* operator new(size_t, void*);
15
16 namespace os {
17 #if OS_HAS_NULLPTR
18 typedef decltype(nullptr) nullptr_t;
19 #endif
20
21 /*
22 * Reference removal
23 */
24
25 template <class _T> struct remove_reference {typedef _T type;};
26 template <class _T> struct remove_reference<_T&> {typedef _T type;};
27 template <class _T> struct remove_reference<_T &&> {typedef _T type;};
28 template <class _T> using remove_reference_t = typename remove_reference<_T>::type;
29
30 /*
31 * Const removal
32 */
33
34 template <class _T> struct remove_const {typedef _T type;};
35 template <class _T> struct remove_const<const _T> {typedef _T type;};
36 template <class _T> using remove_const_t = typename remove_const<_T>::type;
37
38 template <class T> struct is_lvalue_reference { static constexpr bool value = false; };
39 template <class T> struct is_lvalue_reference<T&> { static constexpr bool value = true; };
40
41 /*
42 * Move
43 */
44
45 template <class _T>
46 inline typename remove_reference<_T>::type &&
47 move(_T && _t)
48 {
49 typedef typename os::remove_reference<_T>::type _U;
50 return static_cast<_U &&>(_t);
51 }
52
53 template <class T>
54 T*
55 move(T* first, T* last, T* d_first)
56 {
57 for (; first != last; ++d_first, (void)++first) {
58 *d_first = os::move(*first);
59 }
60 return d_first;
61 }
62
63 template <class T>
64 constexpr T && forward(os::remove_reference_t<T>&t) noexcept {
65 return static_cast<T &&>(t);
66 }
67
68 template <class T>
69 constexpr T && forward(os::remove_reference_t<T>&& t) noexcept {
70 static_assert(!os::is_lvalue_reference<T>::value,
71 "can not forward an rvalue as an lvalue");
72 return static_cast<T &&>(t);
73 }
74
75 // Moves [first, last) into the range ending at d_last,
76 // proceeding backwards (from last to first)
77 // UB if d_last is within (first, last]
78 template <class T>
79 T*
80 move_backward(T* first, T* last, T* d_last)
81 {
82 while (first != last) {
83 *(--d_last) = os::move(*(--last));
84 }
85 return d_last;
86 }
87
88 template <class T>
89 T*
90 uninitialized_move(T* first, T* last, T* d_first)
91 {
92 for (; first != last; ++d_first, (void) ++first) {
93 ::new (static_cast<void*>(d_first)) T(os::move(*first));
94 }
95 return first;
96 }
97
98 template <class T>
99 void
100 destroy(T* first, T* last)
101 {
102 for (; first != last; ++first) {
103 first->~T();
104 }
105 }
106
107 template <class T>
108 void
109 uninitialized_value_construct(T* first, T* last)
110 {
111 for (; first != last; ++first) {
112 ::new (static_cast<void*>(first)) T();
113 }
114 }
115 }
116
117 #endif /* _OS_CPP_UTIL_H */