"ScL Feature"/
SCL Feature 0.0.1
C++20 composable proxy wrapper with pluggable executor strategy
Loading...
Searching...
No Matches
wrapper_constructor_resolver.h
1#pragma once
2
3#include <scl/feature/detail/wrapper_guard.h>
4#include <scl/feature/type_traits/wrapper.h>
5#include <scl/utility/type_traits/forward_like.h>
6
7#include <type_traits>
8#include <utility>
9
10namespace scl::feature::detail
11{
19 template <typename Left, typename Right>
20 class wrapper_constructor_resolver;
21
42 template <typename LeftWrapper, typename RightRefer>
43 requires ::scl::feature::is_wrapper_v<::std::remove_cvref_t<RightRefer>>
44 class guarded_wrapper_constructor_resolver
45 {
46 using guard_type = wrapper_guard<RightRefer, wrapper_guard_case::wrapper>;
47 using inner_refer_t = decltype(::std::declval<guard_type &>().value());
48 using inner_resolver_t = wrapper_constructor_resolver<LeftWrapper, inner_refer_t>;
49
50 public:
51 constexpr explicit guarded_wrapper_constructor_resolver(RightRefer right)
52 : m_guard{::std::forward<RightRefer>(right)}
53 , m_resolver{m_guard.value()}
54 {}
55
56 constexpr decltype(auto) resolve() { return m_resolver.resolve(); }
57
58 private:
59 guard_type m_guard;
60 inner_resolver_t m_resolver;
61 };
62
118 // NOLINTBEGIN(cppcoreguidelines-special-member-functions, bugprone-branch-clone)
119 template <typename LeftValue, template <typename> class LeftExecutor, typename RightRefer>
120 class wrapper_constructor_resolver<wrapper<LeftValue, LeftExecutor>, RightRefer>
121 {
122 using left_type = wrapper<LeftValue, LeftExecutor>;
123 using right_type = ::std::remove_cvref_t<RightRefer>;
124
125 public:
126 explicit constexpr wrapper_constructor_resolver(RightRefer right) noexcept
127 : m_right{::std::forward<RightRefer>(right)}
128 {}
129
130 constexpr wrapper_constructor_resolver(wrapper_constructor_resolver &) = default;
131 constexpr wrapper_constructor_resolver(wrapper_constructor_resolver &&) = default;
132 constexpr wrapper_constructor_resolver(wrapper_constructor_resolver const &) = default;
133
134 constexpr decltype(auto) resolve()
135 {
137 {
138 // strategy 1: same wrapper type — forward the executor directly
139 return executor_access::get(::std::forward<RightRefer>(m_right));
140 }
142 {
143 // strategy 2: right fits into a part of left — forward the right wrapper
144 return ::std::forward<RightRefer>(m_right);
145 }
147 {
148 // strategy 3: right is a wrapper — peel one layer and recurse
149 using right_executor = typename right_type::executor_type;
150 using right_executor_refer = ::scl::forward_like_t<RightRefer, right_executor>;
151
152 constexpr bool has_unguard =
153 requires(right_executor_refer e) {
154 right_executor::template unguard<right_executor_refer>(e);
155 };
156
157 if constexpr (has_unguard)
158 {
159 // unguard exists — need RAII wrapper_guard for guard/unguard bracketing
160 return guarded_wrapper_constructor_resolver<left_type, RightRefer>{
161 ::std::forward<RightRefer>(m_right)}
162 .resolve();
163 }
164 else
165 {
166 // no unguard — no RAII needed; call guard if present, then access value directly
167 decltype(auto) executor = executor_access::get(::std::forward<RightRefer>(m_right));
168
169 if constexpr (
170 requires { right_executor::template guard<right_executor_refer>(executor); })
171 right_executor::template guard<right_executor_refer>(executor);
172
173 decltype(auto) inner = right_executor::template value<right_executor_refer>(
174 ::std::forward<decltype(executor)>(executor));
175
176 return wrapper_constructor_resolver<left_type, decltype(inner)>{
177 ::std::forward<decltype(inner)>(inner)}
178 .resolve();
179 }
180 }
181 else
182 {
183 // strategy 4: plain value — forward as-is
184 return ::std::forward<RightRefer>(m_right);
185 }
186 }
187
188 private:
189 RightRefer m_right;
190 };
191 // NOLINTEND(cppcoreguidelines-special-member-functions, bugprone-branch-clone)
192
193} // namespace scl::feature::detail
constexpr bool is_compatible_with_v
Checks whether Test is compatible with (usable in place of) Expected.
Definition wrapper.h:62
constexpr bool is_compatible_with_part_of_v
Checks whether Expected (a wrapper) recursively contains a value that is compatible with Test (also a...
Definition wrapper.h:101
constexpr bool is_wrapper_v
Checks whether Type is a wrapper specialization.
Definition wrapper.h:28