header_utils
Loading...
Searching...
No Matches
uninitialized.h
1#pragma once
2
3#include <cstddef>
4#include <memory>
5#include <new>
6#include <ranges>
7#include <span>
8#include <type_traits>
9#include <utility>
10
13
14namespace ghassanpl
15{
16 namespace detail
17 {
18 template <typename T>
19 concept default_constructible = requires { ::new (static_cast<void*>(std::declval<T*>())) T; };
20
21 template <typename T, typename... Args>
22 concept paren_constructible_from = requires(Args&&... args) {
23 ::new (static_cast<void*>(std::declval<T*>())) T(std::forward<Args>(args)...);
24 };
25
26 template <typename T, typename... Args>
27 concept brace_constructible_from = requires(Args&&... args) {
28 ::new (static_cast<void*>(std::declval<T*>())) T{ std::forward<Args>(args)... };
29 };
30
31 template <typename T>
32 concept nothrow_default_constructible = noexcept(::new (static_cast<void*>(std::declval<T*>())) T);
33
34 template <typename T, typename... Args>
35 concept nothrow_paren_constructible_from = requires(Args&&... args) {
36 { ::new (static_cast<void*>(std::declval<T*>())) T(std::forward<Args>(args)...) } noexcept;
37 };
38
39 template <typename T, typename... Args>
40 concept nothrow_brace_constructible_from = requires(Args&&... args) {
41 { ::new (static_cast<void*>(std::declval<T*>())) T{ std::forward<Args>(args)... } } noexcept;
42 };
43
44 template <typename T>
45 concept sized = std::is_object_v<T> and requires { sizeof(T); };
46
47 template <typename T>
48 concept const_ref = std::is_reference_v<T> and std::is_const_v<std::remove_reference_t<T>>;
49 }
50
54
55 struct default_init_t {} default_init;
56 struct paren_init_t {} paren_init;
57 struct brace_init_t {} brace_init;
58
60 template <detail::sized T>
61 union unititialized_t
62 {
63 public:
64 constexpr unititialized_t() noexcept {}
65
66 explicit constexpr unititialized_t(default_init_t)
67 noexcept(detail::nothrow_default_constructible<T>)
68 requires detail::default_constructible<T>
69 {
70 this->default_init();
71 }
72
73 template <typename... Args>
74 explicit constexpr unititialized_t(paren_init_t, Args&&... args)
75 noexcept(detail::nothrow_paren_constructible_from<T, Args...>)
76 requires detail::paren_constructible_from<T, Args...>
77 {
78 this->paren_init(std::forward<Args>(args)...);
79 }
80
81 template <typename... Args>
82 explicit constexpr unititialized_t(brace_init_t, Args&&... args)
83 noexcept(detail::nothrow_brace_constructible_from<T, Args...>)
84 requires detail::brace_constructible_from<T, Args...>
85 {
86 this->brace_init(std::forward<Args>(args)...);
87 }
88
89 constexpr ~unititialized_t()
90 requires std::is_trivially_destructible_v<T>
91 = default;
92
93 constexpr ~unititialized_t() {}
94
95 template <typename Self>
96 constexpr auto default_init(this Self&& self)
97 noexcept(detail::nothrow_default_constructible<T>) -> T&
98 requires detail::default_constructible<T>
99 {
100 return *::new (static_cast<void*>(std::addressof(self.object))) T;
101 }
102
103 template <typename Self, typename... Args>
104 constexpr auto paren_init(this Self&& self, Args&&... args)
105 noexcept(detail::nothrow_paren_constructible_from<T, Args...>) -> T&
106 requires detail::paren_constructible_from<T, Args...>
107 {
108 return *::new (static_cast<void*>(std::addressof(self.object)))
109 T(std::forward<Args>(args)...);
110 }
111
112 template <typename Self, typename... Args>
113 constexpr auto brace_init(this Self&& self, Args&&... args)
114 noexcept(detail::nothrow_brace_constructible_from<T, Args...>) -> T&
115 requires detail::brace_constructible_from<T, Args...>
116 {
117 return *::new (static_cast<void*>(std::addressof(self.object)))
118 T{ std::forward<Args>(args)... };
119 }
120
121 template <typename Self>
122 [[nodiscard]] constexpr auto ptr(this Self&& self) noexcept -> auto*
123 {
124 return std::addressof(self.object);
125 }
126
127 template <typename Self>
128 [[nodiscard]] constexpr auto operator->(this Self&& self) noexcept -> auto*
129 {
130 return std::addressof(self.object);
131 }
132
133 template <typename Self>
134 [[nodiscard]] constexpr auto ref(this Self&& self) noexcept -> auto&&
135 {
136 return std::forward<Self>(self).object;
137 }
138
139 template <typename Self>
140 [[nodiscard]] constexpr auto operator*(this Self&& self) noexcept -> auto&&
141 {
142 return std::forward<Self>(self).object;
143 }
144
145 template <typename Self>
146 [[nodiscard]] constexpr auto bytes(this Self&& self) noexcept -> std::ranges::borrowed_range auto
147 {
148 using byte_type = std::conditional_t<
149 detail::const_ref<Self> or std::is_const_v<T>,
150 std::byte const,
151 std::byte>;
152 return std::span<byte_type, sizeof(T)>(
153 reinterpret_cast<byte_type*>(std::addressof(self.object)),
154 sizeof(T)
155 );
156 }
157
158 template <typename Self>
159 constexpr auto destroy(this Self&& self) noexcept(std::is_nothrow_destructible_v<T>)
160 {
161 if constexpr (not std::is_trivially_destructible_v<T>)
162 std::destroy_at(std::addressof(self.object));
163 }
164
165 private:
166 T object;
167 };
168
169 template <detail::sized T>
170 unititialized_t(paren_init_t, T) -> unititialized_t<T>;
171
172 template <detail::sized T>
173 unititialized_t(brace_init_t, T) -> unititialized_t<T>;
174
176}
struct ghassanpl::default_init_t default_init
Constructor tag to default-construct the object inside an unititialized_t.
struct ghassanpl::paren_init_t paren_init
Constructor tag to paren-construct the object inside an unititialized_t.
struct ghassanpl::brace_init_t brace_init
Constructor tag to brace-construct the object inside an unititialized_t.
Primary namespace for everything in this library.
Definition align+rec2.h:10
unititialized_t<T> is an appropriately sized and aligned storage for type T, with a useful interface ...