blob: 0ab09eee6c2a053b5684647e23bc326d2be4b386 (
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
61
62
63
|
#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) &
{
new(uninit_ptr()) T(ASL_FWD(args)...);
}
// @Safety Must be called only when in initialized state.
constexpr void uninit_unsafe() &
{
if constexpr (!trivially_destructible<T>)
{
init_ptr_unsafe()->~T();
}
}
};
} // namespace asl
|