xref: /xnu-8019.80.24/libkern/os/cpp_util.h (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
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*) noexcept;
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 */
118