7#include <initializer_list>
12USERVER_NAMESPACE_BEGIN
24class AnyMovable
final {
31 AnyMovable& operator=(AnyMovable&&)
noexcept =
default;
35 template <
typename ValueType,
typename = std::enable_if_t<!std::is_same_v<AnyMovable, std::decay_t<ValueType>>>>
39 template <
typename ValueType,
typename... Args>
40 explicit AnyMovable(std::in_place_type_t<ValueType> tag, Args&&... args);
43 template <
typename ValueType,
typename Item,
typename... Args>
44 explicit AnyMovable(std::in_place_type_t<ValueType> tag, std::initializer_list<Item> list, Args&&... args);
48 template <
typename ValueType>
49 AnyMovable&
operator=(ValueType&& rhs);
58 template <
typename ValueType,
typename... Args>
59 ValueType&
Emplace(Args&&... args);
62 template <
typename ValueType,
typename Item,
typename... Args>
63 ValueType&
Emplace(std::initializer_list<Item> list, Args&&... args);
68 template <
typename ValueType>
71 struct HolderDeleter {
75 template <
typename ValueType>
76 friend ValueType*
AnyCast(AnyMovable*)
noexcept;
78 template <
typename ValueType>
79 friend const ValueType*
AnyCast(
const AnyMovable*)
noexcept;
81 std::unique_ptr<
HolderBase, HolderDeleter> content_;
85class BadAnyMovableCast
final :
public std::bad_any_cast {
87 const char* what()
const noexcept override;
92template <
typename ValueType>
93ValueType*
AnyCast(AnyMovable* operand)
noexcept;
97template <
typename ValueType>
98const ValueType*
AnyCast(
const AnyMovable* operand)
noexcept;
103template <
typename ValueType>
104ValueType
AnyCast(AnyMovable& operand);
109template <
typename ValueType>
110ValueType
AnyCast(
const AnyMovable& operand);
115template <
typename ValueType>
116ValueType
AnyCast(AnyMovable&& operand);
119 using DeleterType =
void (*)(
HolderBase&)
noexcept;
124template <
typename ValueType>
125struct AnyMovable::Holder
final :
public HolderBase {
127 std::is_same_v<ValueType, std::decay_t<ValueType>>,
128 "The requested type can't be stored in an AnyMovable"
133 static void Deleter(
HolderBase& holder)
noexcept {
delete &
static_cast<Holder&>(holder); }
135 template <
typename... Args>
136 static std::unique_ptr<
HolderBase, HolderDeleter> Make(Args&&... args) {
138 return std::unique_ptr<
HolderBase, HolderDeleter>{
141 new Holder{{&Deleter}, ValueType(std::forward<Args>(args)...)}};
144 static ValueType* GetIf(
const AnyMovable* any)
noexcept {
145 return (any && any->content_ && any->content_->deleter == &Deleter) ? &
static_cast<Holder&>(*any->content_).held
150template <
typename ValueType,
typename>
152 : content_(Holder<std::decay_t<ValueType>>::Make(std::forward<ValueType>(value))) {
154 !std::is_same_v<AnyMovable*, std::decay_t<ValueType>> &&
155 !std::is_same_v<
const AnyMovable*, std::decay_t<ValueType>>,
156 "AnyMovable misuse detected: trying to wrap AnyMovable* in another "
157 "AnyMovable. The pointer was probably meant to be dereferenced."
161template <
typename ValueType,
typename... Args>
162AnyMovable::
AnyMovable(std::in_place_type_t<ValueType> , Args&&... args)
163 : content_(Holder<ValueType>::Make(std::forward<Args>(args)...)) {}
165template <
typename ValueType,
typename Item,
typename... Args>
166AnyMovable::
AnyMovable(std::in_place_type_t<ValueType> , std::initializer_list<Item> list, Args&&... args)
167 : content_(Holder<ValueType>::Make(list, std::forward<Args>(args)...)) {}
169template <
typename ValueType>
170AnyMovable& AnyMovable::
operator=(ValueType&& rhs) {
171 *
this = AnyMovable(std::forward<ValueType>(rhs));
175template <
typename ValueType,
typename... Args>
176ValueType& AnyMovable::
Emplace(Args&&... args) {
177 content_ = Holder<ValueType>::Make(std::forward<Args>(args)...);
178 return static_cast<Holder<ValueType>&>(*content_).held;
181template <
typename ValueType,
typename Item,
typename... Args>
182ValueType& AnyMovable::
Emplace(std::initializer_list<Item> list, Args&&... args) {
183 content_ = Holder<ValueType>::Make(list, std::forward<Args>(args)...);
184 return static_cast<Holder<ValueType>&>(*content_).held;
187template <
typename ValueType>
188ValueType*
AnyCast(AnyMovable* operand)
noexcept {
189 return AnyMovable::Holder<ValueType>::GetIf(operand);
192template <
typename ValueType>
193const ValueType*
AnyCast(
const AnyMovable* operand)
noexcept {
194 return AnyMovable::Holder<ValueType>::GetIf(operand);
197template <
typename ValueType>
201 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
202 auto* result = AnyCast<NonRef>(&operand);
203 if (!result)
throw BadAnyMovableCast();
204 return static_cast<ValueType>(*result);
207template <
typename ValueType>
211 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
212 auto* result = AnyCast<NonRef>(&operand);
213 if (!result)
throw BadAnyMovableCast();
214 return static_cast<ValueType>(*result);
217template <
typename ValueType>
219 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
220 auto* result = AnyCast<NonRef>(&operand);
221 if (!result)
throw BadAnyMovableCast();
222 return static_cast<ValueType>(std::move(*result));