3#include <scl/feature/concepts/wrapper.h>
4#include <scl/feature/detail/wrapper_lock.h>
5#include <scl/utility/concepts/reference.h>
6#include <scl/utility/type_traits/forward_like.h>
13namespace scl::feature::detail
15 enum class value_lock_case :
bool
21 template <::scl::concepts::reference Refer,
25 template <::scl::concepts::reference Refer>
26 class value_lock<Refer, value_lock_case::value>
29 value_lock(value_lock &&) =
delete;
30 value_lock(value_lock
const &) =
delete;
31 value_lock & operator=(value_lock &&) =
delete;
32 value_lock & operator=(value_lock
const &) =
delete;
33 ~value_lock() =
default;
35 constexpr explicit value_lock(Refer ref) noexcept
36 : m_ref{::std::forward<Refer>(ref)}
39 template <::std::convertible_to<Refer> Target>
40 static constexpr void lock_for() noexcept
43 template <::std::convertible_to<Refer> Target>
45 constexpr Target value_as() noexcept(::std::is_nothrow_convertible_v<Refer, Target>)
47 return ::std::forward<Refer>(m_ref);
55 template <concepts::wrapper_reference WrapperRefer>
56 class value_lock<WrapperRefer, value_lock_case::wrapper>
58 using wrapper_type = ::std::remove_cvref_t<WrapperRefer>;
59 using value_type =
typename wrapper_type::value_type;
60 using value_refer = ::scl::forward_like_t<WrapperRefer, value_type>;
62 using outer_lock_type = ::scl::feature::detail::wrapper_lock<WrapperRefer, wrapper_lock_case::wrapper>;
63 using inner_lock_type = ::scl::feature::detail::value_lock<value_refer,
67 value_lock(value_lock &&) =
delete;
68 value_lock(value_lock
const &) =
delete;
69 value_lock & operator=(value_lock &&) =
delete;
70 value_lock & operator=(value_lock
const &) =
delete;
72 constexpr explicit value_lock(WrapperRefer ref)
73 noexcept(
noexcept(outer_lock_type{::std::declval<WrapperRefer>()}))
74 : m_outer_lock{::std::forward<WrapperRefer>(ref)}
77 constexpr ~value_lock()
78 noexcept(::std::is_nothrow_destructible_v<inner_lock_type> && ::std::is_nothrow_destructible_v<outer_lock_type>)
80 if (m_outer_lock.locked())
81 ::std::destroy_at(::std::addressof(m_inner_lock));
84 template <concepts::convertible_from<WrapperRefer> Target>
85 constexpr void lock_for() noexcept(lock_for_noexcept<Target>())
87 if constexpr (!::std::is_convertible_v<WrapperRefer, Target>)
90 ::std::construct_at(::std::addressof(m_inner_lock), m_outer_lock.value());
91 m_inner_lock.template lock_for<Target>();
95 template <concepts::convertible_from<WrapperRefer> Target>
97 constexpr Target value_as() noexcept(value_as_noexcept<Target>())
99 if constexpr (!::std::is_convertible_v<WrapperRefer, Target>)
101 assert(m_outer_lock.locked() &&
"value_as<Target>() requires a prior lock_for<Target>()");
102 return m_inner_lock.template value_as<Target>();
105 return m_outer_lock.wrapper_value();
109 template <
typename Target>
110 static constexpr bool lock_for_noexcept() noexcept
112 if constexpr (::std::is_convertible_v<WrapperRefer, Target>)
115 return noexcept(::std::declval<outer_lock_type &>().lock()) &&
116 noexcept(::std::declval<outer_lock_type &>().value()) &&
117 noexcept(inner_lock_type{::std::declval<outer_lock_type &>().value()}) &&
118 noexcept(::std::declval<inner_lock_type &>().
template lock_for<Target>());
121 template <
typename Target>
122 static constexpr bool value_as_noexcept() noexcept
124 if constexpr (::std::is_convertible_v<WrapperRefer, Target>)
125 return noexcept(::std::declval<outer_lock_type &>().wrapper_value());
127 return noexcept(::std::declval<inner_lock_type &>().template value_as<Target>());
131 outer_lock_type m_outer_lock;
135 inner_lock_type m_inner_lock;
constexpr bool is_wrapper_v
Checks whether Type is a wrapper specialization.
Definition wrapper.h:32