"ScL Feature"/
ScL Feature 0.0.1
C++20 composable proxy wrapper with pluggable executor strategy
Loading...
Searching...
No Matches
wrapper_cast.h
1#pragma once
2
3#include <scl/feature/concepts/wrapper.h>
4#include <scl/feature/detail/value_lock.h>
5#include <scl/feature/type_traits/wrapper.h>
6#include <scl/utility/concepts/reference.h>
7#include <scl/utility/type_traits/forward_like.h>
8
9#include <type_traits>
10#include <utility>
11
12namespace scl::feature::detail
13{
14 enum class wrapper_cast_case : bool
15 {
16 value = false,
17 wrapper = true,
18 };
19
20 // -------------------------------------------------------------------------
21 // cast_mixin — CRTP base that injects one implicit conversion operator per
22 // reachable level in the wrapper chain.
23 //
24 // The bool parameter IsWrapper routes to the two specialisations below,
25 // avoiding macros while covering all cv-ref combinations.
26 // -------------------------------------------------------------------------
27
28 template <typename Caster,
29 ::scl::concepts::reference Refer,
30 wrapper_cast_case Case = ::scl::feature::is_wrapper_v<Refer> ? wrapper_cast_case::wrapper : wrapper_cast_case::value>
31 class cast_mixin;
32
33 // Non-wrapper leaf: one operator for the plain reference type.
34 template <typename Caster, ::scl::concepts::reference Refer>
35 class cast_mixin<Caster, Refer, wrapper_cast_case::value>
36 {
37 public:
38 [[nodiscard]]
39 constexpr
40 operator Refer() && noexcept(noexcept(::std::declval<Caster &&>().template to<Refer>()))
41 {
42 return static_cast<Caster &&>(*this).template to<Refer>();
43 }
44 };
45
46 // Wrapper level: one operator for the wrapper reference itself plus
47 // inherited operators for every inner level via recursive base.
48 template <typename Caster, concepts::wrapper_reference WrapperRefer>
49 class cast_mixin<Caster, WrapperRefer, wrapper_cast_case::wrapper>
50 : public cast_mixin<Caster, ::scl::forward_like_t<WrapperRefer, typename ::std::remove_cvref_t<WrapperRefer>::value_type>>
51 {
52 public:
53 [[nodiscard]]
54 operator WrapperRefer() && noexcept(noexcept(::std::declval<Caster &&>().template to<WrapperRefer>()))
55 {
56 return static_cast<Caster &&>(*this).template to<WrapperRefer>();
57 }
58 };
59
60 // -------------------------------------------------------------------------
61 // wrapper_caster — lazy-locking proxy returned by wrapper_cast().
62 //
63 // Constructs a value_lock (all executor references stored, no guard yet).
64 // Each implicit conversion operator (provided by cast_mixin) calls to<T>()
65 // which activates the necessary guards just before returning the value.
66 //
67 // All conversions are &&-qualified: the caster must be used as an rvalue.
68 // Copy and move constructors are deleted to prevent moving the lock state.
69 // -------------------------------------------------------------------------
70
71 template <::scl::concepts::reference Refer>
72 class [[nodiscard]]
73 wrapper_caster : public cast_mixin<wrapper_caster<Refer>, Refer>
74 {
75 using lock_type = ::scl::feature::detail::value_lock<Refer,
76 ::scl::feature::is_wrapper_v<Refer> ? value_lock_case::wrapper : value_lock_case::value>;
77
78 public:
79 wrapper_caster(wrapper_caster &&) = delete;
80 wrapper_caster(wrapper_caster const &) = delete;
81 wrapper_caster & operator=(wrapper_caster &&) = delete;
82 wrapper_caster & operator=(wrapper_caster const &) = delete;
83 ~wrapper_caster() = default;
84
85 constexpr explicit wrapper_caster(Refer ref) noexcept
86 : m_lock{::std::forward<Refer>(ref)}
87 {}
88
91 template <concepts::convertible_from<Refer> Type>
92 [[nodiscard]]
93 constexpr Type to() && /**/
94 noexcept(noexcept(::std::declval<lock_type &>().template lock_for<Type>()) &&
95 noexcept(::std::declval<lock_type &>().template value_as<Type>()))
96 {
97 m_lock.template lock_for<Type>();
98 return m_lock.template value_as<Type>();
99 }
100
101 private:
102 lock_type m_lock;
103 };
104
105} // namespace scl::feature::detail
constexpr bool is_wrapper_v
Checks whether Type is a wrapper specialization.
Definition wrapper.h:32