130 !std::is_reference<T>::value,
131 "====================> AUI: attempt to use aui::no_escape with reference type. Please use undecorated type "
132 "(without reference)");
134 !std::is_pointer_v<T>,
135 "====================> AUI: attempt to use aui::no_escape with pointer type. Please use undecorated type "
136 "(without pointer)");
142 no_escape(T& value) : value(&value) {
AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null"); }
145 no_escape(T&& value) : value(&value) {
AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null"); }
146 no_escape(T* value) : value(value) {
AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null"); }
148 no_escape(
const _<T>& value) : value(&*value) {
149 AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null");
151 no_escape(
const _unique<T>& value) : value(&*value) {
152 AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null");
156 typename DerivedFromT,
157 std::enable_if_t<std::is_base_of_v<T, DerivedFromT> && !std::is_same_v<DerivedFromT, T>,
bool> =
true>
159 AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null");
163 typename DerivedFromT,
164 std::enable_if_t<std::is_base_of_v<T, DerivedFromT> && !std::is_same_v<DerivedFromT, T>,
bool> =
true>
165 no_escape(
const _unique<DerivedFromT>& value) : value(&*value) {
166 AUI_ASSERTX(no_escape::value !=
nullptr,
"the argument could not be null");
170 T* ptr()
const noexcept {
174 T* operator->()
const noexcept {
return value; }
176 T& operator*()
const noexcept {
return *value; }
186 struct EvaluationLoopTrap {};
187 mutable std::variant<std::nullopt_t, T, EvaluationLoopTrap> value = std::nullopt;
188 std::function<T()> initializer;
191 template <
typename Factory, std::enable_if_t<std::is_invocable_r_v<T, Factory>,
bool> = true>
192 lazy(
Factory&& initializer) noexcept : initializer(std::forward<Factory>(initializer)) {}
194 lazy(
const lazy<T>& other) noexcept : value(other.value), initializer(other.initializer) {}
195 lazy(lazy<T>&& other) noexcept : value(std::move(other.value)), initializer(std::move(other.initializer)) {}
198 if (std::holds_alternative<T>(value)) {
199 return std::get<T>(value);
201 if (std::holds_alternative<std::nullopt_t>(value)) {
202 setEvaluationLoopTrap();
203 value = initializer();
204 return std::get<T>(value);
206 detail::evaluationLoop();
210 void setEvaluationLoopTrap() { value = EvaluationLoopTrap {}; }
212 const T& get()
const {
return const_cast<lazy<T>*
>(
this)->get(); }
214 operator T&() {
return get(); }
215 operator const T&()
const {
return get(); }
217 T& operator*() {
return get(); }
218 const T& operator*()
const {
return get(); }
220 T* operator->() {
return &get(); }
221 T
const* operator->()
const {
return &get(); }
223 lazy<T>& operator=(T&& t) {
224 value = std::move(t);
227 lazy<T>& operator=(
const T& t) {
232 void reset() { value = std::nullopt; }
234 explicit operator bool()
const noexcept
241 bool hasValue()
const noexcept {
242 return std::holds_alternative<T>(value);
253 mutable bool value =
false;
254 std::function<void()> initializer;
257 template <
typename Factory, std::enable_if_t<std::is_invocable_r_v<
void, Factory>,
bool> = true>
258 lazy(
Factory&& initializer) noexcept : initializer(std::forward<Factory>(initializer)) {}
260 lazy(
const lazy<void>& other) noexcept : value(other.value), initializer(other.initializer) {}
261 lazy(lazy<void>&& other) noexcept : value(other.value), initializer(std::move(other.initializer)) {}
269 void get()
const {
return const_cast<lazy<void>*
>(
this)->get(); }
271 void operator*() {
return get(); }
272 const void operator*()
const {
return get(); }
274 void reset() { value =
false; }
277 bool hasValue()
const noexcept {
292 std::function<T()> initializer;
295 template <
typename Factory, std::enable_if_t<std::is_invocable_r_v<T, Factory>,
bool> = true>
296 atomic_lazy(
Factory&& initializer) : initializer(std::forward<Factory>(initializer)) {}
298 atomic_lazy(
const atomic_lazy<T>& other) {
299 std::unique_lock lock(other.sync);
301 initializer = other.initializer;
303 atomic_lazy(atomic_lazy<T>&& other)
noexcept {
304 std::unique_lock lock(other.sync);
305 value = std::move(other.value);
306 initializer = std::move(other.initializer);
311 std::unique_lock lock(sync);
313 value = initializer();
318 const T& get()
const {
return const_cast<atomic_lazy<T>*
>(
this)->get(); }
320 operator T&() {
return get(); }
321 operator const T&()
const {
return get(); }
323 T& operator*() {
return get(); }
324 const T& operator*()
const {
return get(); }
326 T* operator->() {
return &get(); }
327 T
const* operator->()
const {
return &get(); }
329 atomic_lazy<T>& operator=(T&& t) {
330 std::unique_lock lock(sync);
331 value = std::move(t);
335 atomic_lazy<T>& operator=(
const T& t) {
336 std::unique_lock lock(sync);
342 std::unique_lock lock(sync);
347 bool hasValue()
const noexcept {
348 std::unique_lock lock(sync);
349 return value.hasValue();
#define AUI_ASSERTX(condition, what)
Asserts that the passed condition evaluates to true. Adds extra message string.
Definition Assert.h:74