"ScL Feature"/
SCL Feature 0.0.1
C++20 composable proxy wrapper with pluggable executor strategy
Loading...
Searching...
No Matches
wrapper_guard.h
1#pragma once
2
3#include <scl/feature/detail/executor_access.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{
12 enum class wrapper_guard_case : bool
13 {
14 value = false,
15 wrapper = true,
16 };
17
18 template <typename Refer, wrapper_guard_case Case>
19 class wrapper_guard;
20
21 template <typename Refer>
22 class wrapper_guard<Refer, wrapper_guard_case::value>
23 {
24 static_assert(::std::is_reference_v<Refer>);
25
26 public:
27 wrapper_guard(wrapper_guard &&) = delete;
28 wrapper_guard(wrapper_guard const &) = delete;
29 wrapper_guard & operator=(wrapper_guard &&) = delete;
30 wrapper_guard & operator=(wrapper_guard const &) = delete;
31 ~wrapper_guard() = default;
32
33 constexpr explicit wrapper_guard(Refer v) noexcept
34 : m_value{::std::forward<Refer>(v)}
35 {}
36
37 constexpr decltype(auto) value() const noexcept { return ::std::forward<Refer>(m_value); }
38
39 private:
40 Refer m_value;
41 };
42
43 template <typename WrapperRefer>
44 class wrapper_guard<WrapperRefer, wrapper_guard_case::wrapper>
45 {
46 static_assert(::std::is_reference_v<WrapperRefer>);
48
49 using wrapper_type = ::std::remove_cvref_t<WrapperRefer>;
50 using executor_type = typename wrapper_type::executor_type;
51 using executor_refer = scl::forward_like_t<WrapperRefer, executor_type>;
52
53 public:
54 wrapper_guard(wrapper_guard &&) = delete;
55 wrapper_guard(wrapper_guard const &) = delete;
56 wrapper_guard & operator=(wrapper_guard &&) = delete;
57 wrapper_guard & operator=(wrapper_guard const &) = delete;
58
59 constexpr explicit wrapper_guard(WrapperRefer w)
60 : m_executor{executor_access::get(::std::forward<WrapperRefer>(w))}
61 {
62 if constexpr (requires { executor_type::template guard<executor_refer>(m_executor); })
63 executor_type::template guard<executor_refer>(m_executor);
64 }
65
66 constexpr ~wrapper_guard()
67 {
68 if constexpr (requires { executor_type::template unguard<executor_refer>(m_executor); })
69 executor_type::template unguard<executor_refer>(m_executor);
70 }
71
72 constexpr decltype(auto) value() const noexcept
73 requires requires {
74 executor_type::template value<executor_refer>(::std::declval<executor_refer>());
75 }
76 {
77 return executor_type::template value<executor_refer>(::std::forward<executor_refer>(m_executor));
78 }
79
80 private:
81 executor_refer m_executor;
82 };
83} // namespace scl::feature::detail
constexpr bool is_wrapper_v
Checks whether Type is a wrapper specialization.
Definition wrapper.h:28
detail::wrapper_guard< Refer, ::scl::feature::is_wrapper_v<::std::remove_cvref_t< Refer > > ? detail::wrapper_guard_case::wrapper :detail::wrapper_guard_case::value > wrapper_guard
RAII guard providing access to the value held by a wrapper or a plain reference.
Definition wrapper_guard.h:29