Dev Essential
Loading...
Searching...
No Matches
stack_ptr_impl.h
Go to the documentation of this file.
1
14
15#ifndef A_UTIL_UTIL_MEMORY_DETAIL_STACK_PTR_IMPL_HEADER_INCLUDED
16#define A_UTIL_UTIL_MEMORY_DETAIL_STACK_PTR_IMPL_HEADER_INCLUDED
17
19#include <new>
20
21namespace a_util {
22namespace memory {
23
24template <typename T, std::size_t StackSize, std::size_t Alignment>
26{
27 new (address()) T();
28 setFlag(InitializeStatus, StackPtrFlags::IsConstructed);
29}
30
31template <typename T, std::size_t StackSize, std::size_t Alignment>
32inline StackPtr<T, StackSize, Alignment>::StackPtr(std::nullptr_t) : _storage()
33{
34}
36template <typename T, std::size_t StackSize, std::size_t Alignment>
37inline StackPtr<T, StackSize, Alignment>::StackPtr(const T& data) : _storage()
39 reset(data);
40}
41
42template <typename T, std::size_t StackSize, std::size_t Alignment>
45 reset(std::move(data));
46}
47
48template <typename T, std::size_t StackSize, std::size_t Alignment>
51 static_assert(StackSize >= sizeof(T), "Array size must be larger");
52 static_assert(alignof(T) <= Alignment, "Alignment must match alignment requirement of T");
54}
55
56template <typename T, std::size_t StackSize, std::size_t Alignment>
58{
59 if (other.isConstructed()) {
60 reset(*other);
61 }
62}
63
64template <typename T, std::size_t StackSize, std::size_t Alignment>
71
72template <typename T, std::size_t StackSize, std::size_t Alignment>
75 if (other.isConstructed()) {
76 this->reset(std::move(*other));
77 }
78}
79
80template <typename T, std::size_t StackSize, std::size_t Alignment>
82{
83 return static_cast<T*>(address());
84}
85
86template <typename T, std::size_t StackSize, std::size_t Alignment>
89 return static_cast<const T*>(address());
90}
91
92template <typename T, std::size_t StackSize, std::size_t Alignment>
97
98template <typename T, std::size_t StackSize, std::size_t Alignment>
100{
101 return *(operator->());
103
104template <typename T, std::size_t StackSize, std::size_t Alignment>
106{
107 return isConstructed();
109
110template <typename T, std::size_t StackSize, std::size_t Alignment>
112{
113 if (isConstructed()) {
114 static_cast<T*>(address())->~T();
115 setFlag(InitializeStatus, StackPtrFlags::IsDestroyed);
116 }
117}
118
119template <typename T, std::size_t StackSize, std::size_t Alignment>
120template <typename... Args>
122{
123 reset();
124 new (address()) T(std::forward<Args>(args)...);
125 setFlag(InitializeStatus, StackPtrFlags::IsConstructed);
126}
128template <typename T, std::size_t StackSize, std::size_t Alignment>
130{
131 using std::swap;
132 StackPtr* reset_after_swap = nullptr;
133 std::size_t remaining_bytes_to_swap = OverheadSize;
134
135 if (this->isConstructed()) {
136 if (!other.isConstructed()) {
137 other.reset(T());
138 reset_after_swap = this;
139 }
140 swap(*(*this), *other);
141 }
142 else if (other.isConstructed()) {
143 this->reset(T());
144 reset_after_swap = &other;
145 swap(*(*this), *other);
146 }
147 else {
148 remaining_bytes_to_swap = StorageSize;
149 }
150
151 // either swap overhead or the entire storage
152 while (remaining_bytes_to_swap) {
153 using std::swap;
154 const std::size_t storage_index = StorageSize - remaining_bytes_to_swap--;
155 swap(this->_storage[storage_index], other._storage[storage_index]);
156 }
157
158 if (reset_after_swap) {
159 reset_after_swap->reset();
160 }
161}
162
163template <typename T, std::size_t StackSize, std::size_t Alignment>
164inline void* StackPtr<T, StackSize, Alignment>::address()
165{
166 return &_storage;
167}
168
169template <typename T, std::size_t StackSize, std::size_t Alignment>
170inline const void* StackPtr<T, StackSize, Alignment>::address() const
171{
172 return &_storage;
173}
174
175template <typename T, std::size_t StackSize, std::size_t Alignment>
176inline void StackPtr<T, StackSize, Alignment>::setFlag(StackPtrFlagPositions position,
177 StackPtrFlags flag)
178{
179 _storage[position] = static_cast<typename std::underlying_type<StackPtrFlags>::type>(flag);
180}
181
182template <typename T, std::size_t StackSize, std::size_t Alignment>
183inline bool StackPtr<T, StackSize, Alignment>::isConstructed() const noexcept
184{
185 return _storage[InitializeStatus] ==
186 static_cast<typename std::underlying_type<StackPtrFlags>::type>(
187 StackPtrFlags::IsConstructed);
188}
189
190template <typename T, std::size_t StackSize, std::size_t Alignment>
192{
193 lhs.swap(rhs);
194}
195
196template <typename T, std::size_t StackSize, std::size_t Alignment>
197inline bool operator==(const StackPtr<T, StackSize, Alignment>& lhs,
198 const StackPtr<T, StackSize, Alignment>& rhs)
199{
200 std::size_t remaining_bytes_to_compare = StackPtr<T, StackSize, Alignment>::OverheadSize;
201 if (!lhs.isConstructed() && !rhs.isConstructed()) {
202 remaining_bytes_to_compare = StackPtr<T, StackSize, Alignment>::StorageSize;
203 }
204 else if (lhs.isConstructed() ^ rhs.isConstructed()) {
205 return false;
206 }
207 else if (!(*lhs == *rhs)) {
208 // fully intended, requires only comparison operator!
209 return false;
210 }
211
212 // don't use memory::compare to avoid link dependency to memory component
213 bool is_equal = true;
214 while (remaining_bytes_to_compare && is_equal) {
215 const std::size_t storage_index =
216 StackPtr<T, StackSize, Alignment>::StorageSize - remaining_bytes_to_compare--;
217 is_equal = lhs._storage[storage_index] == rhs._storage[storage_index];
218 }
219 return is_equal;
220}
221
222template <typename T, std::size_t StackSize, std::size_t Alignment>
225{
226 return !(lhs == rhs);
227}
228
229template <typename T, std::size_t StackSize, std::size_t Alignment, typename... Args>
230constexpr inline auto makeStackPtr(Args&&... args) -> StackPtr<T, StackSize, Alignment>
231{
232 return StackPtr<T, StackSize, Alignment>(T(std::forward<Args>(args)...));
233}
234
235} // namespace memory
236} // namespace a_util
237
238#endif // A_UTIL_UTIL_MEMORY_DETAIL_STACK_PTR_IMPLL_HEADER_INCLUDED
Definition stack_ptr_decl.h:32
void reset()
Definition stack_ptr_impl.h:111
StackPtr & operator=(StackPtr other)
Definition stack_ptr_impl.h:65
StackPtr()
Initializes the storage and constructs object ot type T by calling its default ctor.
Definition stack_ptr_impl.h:25
T * operator->()
Definition stack_ptr_impl.h:81
void swap(StackPtr &other)
Definition stack_ptr_impl.h:129
~StackPtr()
Destructor.
Definition stack_ptr_impl.h:49
T & operator*()
Definition stack_ptr_impl.h:93
Serves as component for memory access and management.
Definition memory.h:20
bool operator!=(const StackPtr< T, StackSize, Alignment > &lhs, const StackPtr< T, StackSize, Alignment > &rhs)
Definition stack_ptr_impl.h:223
void swap(StackPtr< T, StackSize, Alignment > &lhs, StackPtr< T, StackSize, Alignment > &rhs)
Definition stack_ptr_impl.h:191
constexpr auto makeStackPtr(Args &&... args) -> StackPtr< T, StackSize, Alignment >
Definition stack_ptr_impl.h:230
Serves as the root component, with common functionality documented in core functionality.
Definition base.h:24