6#ifndef SL_UNIQUE_HANDLE_HPP
7#define SL_UNIQUE_HANDLE_HPP
22#if __cpp_lib_optional >= 202106L
23#define SL_UNIQUE_HANDLE_FULL_CONSTEXPR constexpr
25#define SL_UNIQUE_HANDLE_FULL_CONSTEXPR
136 struct value_validator
138 static_assert(std::movable<T>,
"The value type must be movable.");
139 static_assert(concepts::not_same_as<std::remove_cvref_t<T>, nullhandle_t>,
"The value type must not be sl::nullhandle_t.");
144 template <
class T,
class TDeleteAction>
145 struct delete_action_validator
147 static_assert(std::copyable<TDeleteAction>,
"The delete action object must be copyable (capturing lambdas are not).");
148 static_assert(std::invocable<TDeleteAction, T&>,
"The delete action object must be invokable by T&.");
150 using type = TDeleteAction;
154 using type_t =
typename T::type;
166 template <
class T,
class TValue>
168 && std::invocable<T, TValue&>
177 template <value T, delete_action_for<T> TDeleteAction = default_delete_action>
181 template <value T2, delete_action_for<T2> TOtherDeleteAction>
204 invoke_delete_action_if_necessary();
214 )
noexcept(std::is_nothrow_move_constructible_v<T>
215 && std::is_nothrow_copy_constructible_v<TDeleteAction>)
216 : m_Value{ std::exchange(other.m_Value, std::nullopt) },
217 m_DeleteAction{ other.m_DeleteAction }
228 )
noexcept(std::is_nothrow_move_constructible_v<T>
229 && std::is_nothrow_move_assignable_v<T>
230 && std::is_nothrow_copy_constructible_v<TDeleteAction>
231 && std::is_nothrow_copy_assignable_v<TDeleteAction>)
235 invoke_delete_action_if_necessary();
237 m_Value = std::exchange(other.m_Value, std::nullopt);
238 m_DeleteAction = other.m_DeleteAction;
250 )
noexcept(std::is_nothrow_move_constructible_v<T>
251 && std::is_nothrow_swappable_v<T>
252 && std::is_nothrow_move_constructible_v<TDeleteAction>
253 && std::is_nothrow_swappable_v<TDeleteAction>)
257 swap(m_Value, other.m_Value);
258 swap(m_DeleteAction, other.m_DeleteAction);
277 : m_Value{ std::nullopt },
278 m_DeleteAction{ deleteAction }
286 invoke_delete_action_if_necessary();
288 m_Value = std::nullopt;
297 : m_Value{ std::nullopt },
298 m_DeleteAction{ deleteAction }
307 template <concepts::initializes<T> T2>
308 requires concepts::not_same_as<std::remove_cvref_t<T2>,
unique_handle>
309 && concepts::not_same_as<std::remove_cvref_t<T2>, nullhandle_t>
310 explicit (!std::convertible_to<T2&&, T>)
312 : m_Value{ std::forward<T2>(
value) },
313 m_DeleteAction{ deleteAction }
322 template <concepts::assignable_to<T&> T2>
323 requires concepts::not_same_as<std::remove_cvref_t<T2>,
unique_handle>
324 && concepts::not_same_as<std::remove_cvref_t<T2>, nullhandle_t>
325 && concepts::initializes<std::remove_cvref_t<T2>, T>
328 invoke_delete_action_if_necessary();
330 m_Value = std::forward<T2>(
value);
339 template <
class... TArgs>
340 requires std::constructible_from<T, TArgs...>
342 : m_Value{ std::in_place, std::forward<TArgs>(args)... }
352 template <
class... TArgs>
353 requires std::constructible_from<T, TArgs...>
355 : m_Value{ std::in_place, std::forward<TArgs>(args)... },
356 m_DeleteAction{ deleteAction }
364 template <
class... TArgs>
365 requires std::constructible_from<T, TArgs...>
368 m_Value.emplace(std::forward<TArgs>(args)...);
376 invoke_delete_action_if_necessary();
387 constexpr const T&
raw()
const {
return m_Value.value(); }
394 constexpr const T&
operator *() const noexcept {
return *m_Value; }
401 constexpr const T*
operator ->() const noexcept {
return &*m_Value; }
408 constexpr explicit operator bool() const noexcept {
return m_Value.has_value(); }
415 constexpr bool is_valid() const noexcept {
return m_Value.has_value(); }
432 template <std::equality_comparable_with<T> T2,
class TOtherDeleteAction>
436 return m_Value == other.m_Value;
447 template <std::three_way_comparable_with<T> T2,
class TOtherDeleteAction>
451 return m_Value <=> other.m_Value;
463 && std::three_way_comparable_with<T, T2>
465 constexpr std::compare_three_way_result_t<T, T2>
operator <=>(
const T2& other)
const
467 return m_Value <=> other;
479 && std::equality_comparable_with<T, T2>
483 return m_Value == other;
507 std::optional<T> m_Value{};
510 TDeleteAction m_DeleteAction{};
512 constexpr void invoke_delete_action_if_necessary() noexcept
515 std::invoke(m_DeleteAction, *m_Value);
525 template <
class T,
class TDeleteAction>
546 template <
class T,
class TDeleteAction>
#define SL_UTILITY_NO_UNIQUE_ADDRESS
Definition: Config.hpp:21
This type models some kind of std::optional behaviour but resets itself on move operations.
Definition: unique_handle.hpp:179
SL_UNIQUE_HANDLE_FULL_CONSTEXPR void reset() noexcept
Resets the value and invokes the delete action if value was initialized.
Definition: unique_handle.hpp:374
TDeleteAction delete_action_type
Type of the used delete action.
Definition: unique_handle.hpp:192
constexpr unique_handle() noexcept=default
Default constructor. The value will be in an uninitialized stated and the delete action gets default ...
constexpr unique_handle(nullhandle_t, const delete_action_type &deleteAction=delete_action_type()) noexcept
Explicitly does not initialize the value. This overload is mainly used for convenience when returning...
Definition: unique_handle.hpp:276
constexpr const T * operator->() const noexcept
Immutable access to the value. No checks will be performed.
Definition: unique_handle.hpp:401
T value_type
Type of the stored value.
Definition: unique_handle.hpp:188
constexpr bool operator==(const unique_handle< T2, TOtherDeleteAction > &other) const
Equality-comparison operator overload between two unique_handles. operator != is implicitly defined.
Definition: unique_handle.hpp:434
friend class unique_handle
Definition: unique_handle.hpp:182
constexpr bool is_valid() const noexcept
Checks whether the value is initialized.
Definition: unique_handle.hpp:415
constexpr void swap(unique_handle &other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_swappable_v< T > &&std::is_nothrow_move_constructible_v< TDeleteAction > &&std::is_nothrow_swappable_v< TDeleteAction >)
Swaps the target and the source in a more efficient way.
Definition: unique_handle.hpp:248
constexpr unique_handle(const delete_action_type &deleteAction) noexcept
Constructor overload for explicitly providing a delete action.
Definition: unique_handle.hpp:296
constexpr std::compare_three_way_result_t< T, T2 > operator<=>(const unique_handle< T2, TOtherDeleteAction > &other) const
Three-way-comparison operator overload between two unique_handles.
Definition: unique_handle.hpp:449
unique_handle(const unique_handle &)=delete
Explicitly deleted copy constructor.
SL_UNIQUE_HANDLE_FULL_CONSTEXPR unique_handle(unique_handle &&other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_copy_constructible_v< TDeleteAction >)
Move constructor, which relocates the ownership of the value to the target and resets the source....
Definition: unique_handle.hpp:212
constexpr unique_handle(std::in_place_t, TArgs &&... args)
Constructor overload for directly initializing the value with a set of arguments.
Definition: unique_handle.hpp:341
constexpr unique_handle(std::in_place_t, const delete_action_type &deleteAction, TArgs &&... args)
Constructor overload for directly initializing the value with a set of arguments and also initializin...
Definition: unique_handle.hpp:354
constexpr const T & operator*() const noexcept
Immutable access to the value. No checks will be performed.
Definition: unique_handle.hpp:394
constexpr const delete_action_type & delete_action() const noexcept
Immutable access to the delete action.
Definition: unique_handle.hpp:422
constexpr const T & raw() const
Immutable access to the value. No checks will be performed.
Definition: unique_handle.hpp:387
SL_UNIQUE_HANDLE_FULL_CONSTEXPR void emplace(TArgs &&... args)
Constructor overload for directly initializing the value with a set of arguments.
Definition: unique_handle.hpp:366
!std ::convertible_to< T2 &&, T > constexpr unique_handle(T2 &&value, const delete_action_type &deleteAction=delete_action_type{})
Constructor overload for initializing the value.
Definition: unique_handle.hpp:311
SL_UNIQUE_HANDLE_FULL_CONSTEXPR unique_handle & operator=(unique_handle &&other) noexcept(std::is_nothrow_move_constructible_v< T > &&std::is_nothrow_move_assignable_v< T > &&std::is_nothrow_copy_constructible_v< TDeleteAction > &&std::is_nothrow_copy_assignable_v< TDeleteAction >)
Move assignment, which relocates the ownership of the value to the target and resets the source....
Definition: unique_handle.hpp:226
Checks whether the left-hand-side type is unequal to the right-hand-side type.
Definition: stl_extensions.hpp:69
Checks whether the given template type is usable as delete action type for unique_handle types.
Definition: unique_handle.hpp:167
Checks whether the given template type is usable as value type for unique_handle types.
Definition: unique_handle.hpp:161
unique_handle(T) -> unique_handle< T >
Deduction guide for unique_handle class.
constexpr nullhandle_t nullhandle
an object of type nullhandle_t
Definition: unique_handle.hpp:114
std::bad_optional_access bad_handle_access
exception type which indicates checked access to an uninitialized value
Definition: unique_handle.hpp:119
unique_handle(T, TDeleteAction) -> unique_handle< detail::type_t< detail::value_validator< T > >, detail::type_t< detail::delete_action_validator< T, TDeleteAction > > >
Deduction guide for unique_handle class.
Definition: operators.hpp:15
default delete action for unique_handle with an empty operator ()
Definition: unique_handle.hpp:125
constexpr void operator()(auto &) const noexcept
Empty invoke operator.
Definition: unique_handle.hpp:129
typename unique_handle< T, TDeleteAction >::value_type value_type
Definition: unique_handle.hpp:549
The main trait, which may be specialized from.
Definition: base.hpp:97
helper type for indicating unique_handles with uninitialized state
Definition: unique_handle.hpp:108
#define SL_UNIQUE_HANDLE_FULL_CONSTEXPR
Definition: unique_handle.hpp:25