Iros
 
Loading...
Searching...
No Matches
rebindable_box.h
Go to the documentation of this file.
1#pragma once
2
3#include "di/meta/core.h"
5#include "di/meta/trivial.h"
6#include "di/meta/util.h"
7#include "di/meta/vocab.h"
8#include "di/types/in_place.h"
9#include "di/util/addressof.h"
11#include "di/util/destroy_at.h"
12#include "di/util/forward.h"
14#include "di/util/move.h"
15#include "di/util/swap.h"
16
17namespace di::util {
18// Rebindable box is a wrapper around a type T or a reference T&,
19// which always has rebind semantics on assignment. In particular,
20// RebindableBox<T&>::operator= will change not assign-through to
21// the object referenced. In addition, the assignment operator is
22// defined even if the underlying T does not support it, as long
23// as it is constructible from what is being assigned to it. Thus,
24// a RebindableBox can rebind structures which contain references.
25template<typename T>
26class RebindableBox;
27
28namespace detail {
29 template<typename T, typename U>
36
37 template<typename T>
39}
40
41template<typename T>
43private:
44 using Storage = meta::WrapReference<T>;
45
46public:
47 constexpr RebindableBox()
49 = default;
50
51 constexpr RebindableBox(RebindableBox const&)
53 = delete;
54 constexpr RebindableBox(RebindableBox const&) = default;
55
58 = default;
59
60 template<typename U>
64 : m_storage(other.value()) {}
65
66 template<typename U>
70 : m_storage(util::move(other).value()) {}
71
72 template<typename U>
75 constexpr explicit RebindableBox(U&& value) : m_storage(util::forward<U>(value)) {}
76
77 template<typename... Args>
78 requires(concepts::ConstructibleFrom<Storage, Args...>)
79 constexpr RebindableBox(types::InPlace, Args&&... args) : m_storage(util::forward<Args>(args)...) {}
80
81 template<typename U, typename... Args>
83 constexpr RebindableBox(types::InPlace, std::initializer_list<U> list, Args&&... args)
84 : m_storage(list, util::forward<Args>(args)...) {}
85
86 constexpr ~RebindableBox() = default;
87
88 constexpr auto operator=(RebindableBox const&) -> RebindableBox& = default;
89 constexpr auto operator=(RebindableBox&&) -> RebindableBox& = default;
90
91 constexpr auto operator=(RebindableBox const& other)
94 rebind(other.value());
95 return *this;
96 }
97
98 constexpr auto operator=(RebindableBox const& other)
101 rebind(util::move(other).value());
102 return *this;
103 }
104
105 template<typename U>
107 constexpr auto operator=(RebindableBox<U> const& other) -> RebindableBox& {
108 rebind(other.value());
109 return *this;
110 }
111
112 template<typename U>
114 constexpr auto operator=(RebindableBox<U>&& other) -> RebindableBox& {
115 rebind(util::move(other).value());
116 return *this;
117 }
118
119 template<typename U = T>
122 constexpr auto operator=(U&& value) -> RebindableBox& {
123 rebind(util::forward<U>(value));
124 return *this;
125 }
126
127 constexpr auto value() & -> T& { return m_storage; }
128 constexpr auto value() const& -> T const& { return m_storage; }
129 constexpr auto value() && -> T&& { return util::move(m_storage); }
130 constexpr auto value() const&& -> T const&& { return util::move(m_storage); }
131
132 template<typename... Args>
133 requires(concepts::ConstructibleFrom<T, Args...>)
134 constexpr auto emplace(Args&&... args) -> T& {
135 util::destroy_at(util::addressof(m_storage));
136 util::construct_at(util::addressof(m_storage), util::forward<Args>(args)...);
137 return value();
138 }
139
140 template<typename U, typename... Args>
142 constexpr auto emplace(std::initializer_list<U> list, Args&&... args) -> T& {
143 util::destroy_at(util::addressof(m_storage));
144 util::construct_at(util::addressof(m_storage), list, util::forward<Args>(args)...);
145 return value();
146 }
147
148private:
149 template<typename U>
150 constexpr void rebind(U&& new_value) {
151 constexpr bool const_assignable = concepts::AssignableFrom<T const&, U>;
152 constexpr bool assignable = concepts::AssignableFrom<T&, U>;
153
154 // Any type T which is const-assignable, must be, by definition, a reference
155 // or a proxy reference. Therefore, it must be rebound. Also, rebinding is
156 // required if the type is out-right not assignable.
157 if constexpr (const_assignable || !assignable) {
158 util::destroy_at(util::addressof(this->value()));
159 util::construct_at(util::addressof(m_storage), util::forward<U>(new_value));
160 } else {
161 m_storage = util::forward<U>(new_value);
162 }
163 }
164
165 Storage m_storage {};
166};
167
168template<typename T>
170
171template<typename T>
172constexpr auto make_rebindable_box(T&& value) {
173 return RebindableBox<meta::UnwrapRefDecay<T>> { util::forward<T>(value) };
174}
175}
176
177namespace di {
179}
Definition rebindable_box.h:42
constexpr auto value() const &&-> T const &&
Definition rebindable_box.h:130
constexpr auto operator=(RebindableBox const &) -> RebindableBox &=default
constexpr auto value() &&-> T &&
Definition rebindable_box.h:129
constexpr auto value() &-> T &
Definition rebindable_box.h:127
constexpr RebindableBox(RebindableBox &&)=default
constexpr auto operator=(RebindableBox const &other) -> RebindableBox &requires(!concepts::TriviallyMoveAssignable< Storage > &&concepts::MoveConstructible< Storage >)
Definition rebindable_box.h:98
constexpr ~RebindableBox()=default
constexpr RebindableBox(RebindableBox const &)=delete
constexpr RebindableBox(types::InPlace, Args &&... args)
Definition rebindable_box.h:79
constexpr RebindableBox()=default
constexpr auto operator=(RebindableBox const &other) -> RebindableBox &requires(!concepts::TriviallyCopyAssignable< Storage > &&concepts::CopyConstructible< Storage >)
Definition rebindable_box.h:91
constexpr auto operator=(RebindableBox &&) -> RebindableBox &=default
constexpr RebindableBox(RebindableBox const &)=default
constexpr auto value() const &-> T const &
Definition rebindable_box.h:128
constexpr auto emplace(std::initializer_list< U > list, Args &&... args) -> T &
Definition rebindable_box.h:142
constexpr RebindableBox(U &&value)
Definition rebindable_box.h:75
constexpr auto emplace(Args &&... args) -> T &
Definition rebindable_box.h:134
constexpr RebindableBox(types::InPlace, std::initializer_list< U > list, Args &&... args)
Definition rebindable_box.h:83
Definition operations.h:19
Definition operations.h:11
Definition operations.h:99
Definition operations.h:34
Definition operations.h:24
Definition core.h:139
Definition operations.h:43
Definition rebindable_box.h:38
detail::WrapReference< T >::Type WrapReference
Definition vocab.h:116
Definition clamp.h:9
Definition vocab.h:96
RebindableBox(T &&) -> RebindableBox< meta::UnwrapRefDecay< T > >
constexpr auto make_rebindable_box(T &&value)
Definition rebindable_box.h:172
constexpr auto destroy_at
Definition destroy_at.h:24
constexpr auto construct_at
Definition construct_at.h:27
Definition zstring_parser.h:9
Definition in_place.h:4