blob: e59cfe0266b221c8fb9a13d3e23258acbbfdc58d (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
#pragma once
#include "asl/layout.hpp"
#include "asl/memory.hpp"
#include "asl/meta.hpp"
#include "asl/utility.hpp"
namespace asl
{
template<is_object T>
class maybe_uninit
{
union
{
alignas(align_of<T>) char m_storage[size_of<T>];
T m_value;
};
public:
constexpr maybe_uninit() {} // NOLINT(*-member-init)
maybe_uninit(const maybe_uninit&) = delete;
maybe_uninit(maybe_uninit&&) = delete;
maybe_uninit& operator=(const maybe_uninit&) = delete;
maybe_uninit& operator=(maybe_uninit&&) = delete;
constexpr ~maybe_uninit() = default;
constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {}
constexpr void* uninit_ptr() && = delete;
constexpr const void* uninit_ptr() const& { return m_storage; }
constexpr void* uninit_ptr() & { return m_storage; }
// @Safety Pointer must only be accessed when in initialized state.
constexpr T* init_ptr_unsafe() && = delete;
constexpr const T* init_ptr_unsafe() const& { return &m_value; }
constexpr T* init_ptr_unsafe() & { return &m_value; }
// @Safety Reference must only be accessed when in initialized state.
constexpr T&& as_init_unsafe() && { return ASL_MOVE(m_value); }
constexpr const T& as_init_unsafe() const& { return m_value; }
constexpr T& as_init_unsafe() & { return m_value; }
// @Safety Must be called only when in uninitialized state.
template<typename... Args>
constexpr void init_unsafe(Args&&... args) &
{
construct_at<T>(uninit_ptr(), ASL_FWD(args)...);
}
// @Safety Must be called only when in initialized state.
constexpr void uninit_unsafe() &
{
destroy(init_ptr_unsafe());
}
};
} // namespace asl
|