"ScL Feature"/
ScL Feature 0.0.1
C++20 composable proxy wrapper with pluggable executor strategy
Loading...
Searching...
No Matches
method.h
Go to the documentation of this file.
1#pragma once
2
44
49#include <scl/feature/wrapper_cast.h>
50#include <scl/utility/preprocessor/forward.h>
51
52#include <type_traits>
53#include <utility>
54
55// clang-format off
56
78#define SCL_REFLECT_METHOD_EXEC_HELPERS(name) \
79 template <typename ScLExec, typename... ScLArgs> \
80 static constexpr bool method_##name##_scl_has_exec_override = \
81 requires { \
82 static_cast< \
83 decltype(::std::remove_cvref_t<ScLExec>::method_##name( \
84 ::std::declval<ScLExec>(), ::std::declval<ScLArgs>()...)) \
85 (*)(ScLExec, ScLArgs...) \
86 >(&::std::remove_cvref_t<ScLExec>::method_##name); \
87 }; \
88 template <typename ScLExec, typename... ScLArgs> \
89 static constexpr bool method_##name##_scl_exec_noexcept = \
90 []() constexpr noexcept -> bool { \
91 if constexpr (method_##name##_scl_has_exec_override<ScLExec, ScLArgs...>) \
92 return noexcept(::std::remove_cvref_t<ScLExec>::method_##name( \
93 ::std::declval<ScLExec>(), ::std::declval<ScLArgs>()...)); \
94 return false; \
95 }();
96
109#define SCL_REFLECT_METHOD_CALLER(name) \
110 struct method_##name##_scl_caller \
111 { \
112 template <typename ScLParam, typename... ScLParams, typename ScLObj, typename... ScLArgs> \
113 static constexpr auto call(ScLObj && scl_obj, ScLArgs &&... scl_args) \
114 -> decltype(::std::forward<ScLObj>(scl_obj).template name<ScLParam, ScLParams...>( \
115 ::scl::wrapper_cast(::std::forward<ScLArgs>(scl_args))...)) \
116 { \
117 return ::std::forward<ScLObj>(scl_obj).template name<ScLParam, ScLParams...>( \
118 ::scl::wrapper_cast(::std::forward<ScLArgs>(scl_args))...); \
119 } \
120 }; \
121
139#define SCL_REFLECT_METHOD_QUALS(name) \
140 template <typename ScLVal, typename... ScLArgs> \
141 static constexpr bool method_##name##_scl_quals = \
142 SCL_HAS_QUALIFIED_METHOD(SCL_FORWARD(name), ScLVal, ScLArgs...); \
143 template <typename ScLParam, typename... ScLParams> \
144 struct method_##name##_scl_template_quals \
145 { \
146 template <typename ScLVal, typename... ScLArgs> \
147 static constexpr bool value = \
148 SCL_HAS_QUALIFIED_METHOD( \
149 SCL_FORWARD(template name<ScLParam, ScLParams...>), \
150 ScLVal, ScLArgs...); \
151 };
152
169#define SCL_REFLECT_METHOD_EXECUTOR_OVERRIDE_BASE(name, cv_ref) \
170 template <typename ScLExec = s_c_l_executor_type cv_ref, typename... ScLArgs> \
171 constexpr decltype(auto) name(ScLArgs &&... scl_args) cv_ref \
172 noexcept(method_##name##_scl_exec_noexcept<ScLExec, ScLArgs...>) \
173 requires \
174 (::std::is_same_v<ScLExec, s_c_l_executor_type cv_ref> \
175 && method_##name##_scl_has_exec_override<ScLExec, ScLArgs...>) \
176 { \
177 return ::std::remove_cvref_t<ScLExec>::method_##name( \
178 SCL_EXECUTOR_ACCESS(cv_ref), \
179 ::std::forward<ScLArgs>(scl_args)...); \
180 }
181
203#define SCL_REFLECT_METHOD_BASE(name, cv_ref) \
204 noexcept (noexcept(SCL_EXECUTE_OVERRIDED(SCL_FORWARD(name), cv_ref))) \
205 requires \
206 (!method_##name##_scl_has_exec_override<s_c_l_executor_type cv_ref, ScLArgs...> && \
207 requires \
208 { \
209 SCL_ACCESS_DECLVAL(cv_ref).name( \
210 ::scl::wrapper_cast(::std::declval<ScLArgs>())...); \
211 } && method_##name##_scl_quals<decltype(SCL_ACCESS_DECLVAL(cv_ref)), \
212 decltype(::scl::wrapper_cast(::std::declval<ScLArgs>()))...>) \
213 { \
214 return SCL_EXECUTE_OVERRIDED(SCL_FORWARD(name), cv_ref); \
215 }
216
242#define SCL_REFLECT_TEMPLATE_METHOD_BASE(name, caller, cv_ref) \
243 noexcept(noexcept(SCL_EXECUTE_TEMPLATE_OVERRIDED(caller, cv_ref))) \
244 requires \
245 requires \
246 { \
247 caller::template call<ScLParam, ScLParams...>( \
248 SCL_ACCESS_DECLVAL(cv_ref), ::std::declval<ScLArgs>()...); \
249 } && method_##name##_scl_template_quals<ScLParam, ScLParams...> \
250 ::template value<decltype(SCL_ACCESS_DECLVAL(cv_ref)), \
251 decltype(::scl::wrapper_cast(::std::declval<ScLArgs>()))...> \
252 { \
253 return SCL_EXECUTE_TEMPLATE_OVERRIDED(caller, cv_ref); \
254 }
255
264#define SCL_REFLECT_METHOD_HELPER(name, caller, cv_ref) \
265 SCL_REFLECT_METHOD_EXECUTOR_OVERRIDE_BASE(name, cv_ref) \
266 template <typename... ScLArgs> \
267 constexpr decltype(auto) name(ScLArgs &&... scl_args) cv_ref \
268 SCL_REFLECT_METHOD_BASE(name, cv_ref) \
269 template <typename ScLParam, typename... ScLParams, typename... ScLArgs> \
270 constexpr decltype(auto) name(ScLArgs &&... scl_args) cv_ref \
271 SCL_REFLECT_TEMPLATE_METHOD_BASE(name, caller, cv_ref)
272
427#define SCL_REFLECT_METHOD(name) \
428 SCL_REFLECT_METHOD_QUALS(name) \
429 SCL_REFLECT_METHOD_CALLER(name) \
430 SCL_REFLECT_METHOD_EXEC_HELPERS(name) \
431 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, &) \
432 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, &&) \
433 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, const &) \
434 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, const &&) \
435 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, volatile &) \
436 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, volatile &&) \
437 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, const volatile &) \
438 SCL_REFLECT_METHOD_HELPER(SCL_FORWARD(name), method_##name##_scl_caller, const volatile &&)
439
440// clang-format on
Internal accessor macros for executor and value access in reflected methods.
Compile-time predicate macro for cv-ref qualifier detection.
Macro for declaring the wrapper type used by reflection macros.
Executor type traits: interface detection and noexcept helpers.