7#include <initializer_list>
12USERVER_NAMESPACE_BEGIN
24class AnyMovable
final {
31 AnyMovable& operator=(AnyMovable&&)
noexcept =
default;
40 template <
typename ValueType,
typename... Args>
41 explicit AnyMovable(std::in_place_type_t<ValueType> tag, Args&&... args);
44 template <
typename ValueType,
typename Item,
typename... Args>
45 explicit AnyMovable(std::in_place_type_t<ValueType> tag,
46 std::initializer_list<Item> list, Args&&... args);
50 template <
typename ValueType>
51 AnyMovable&
operator=(ValueType&& rhs);
60 template <
typename ValueType,
typename... Args>
61 ValueType&
Emplace(Args&&... args);
64 template <
typename ValueType,
typename Item,
typename... Args>
65 ValueType&
Emplace(std::initializer_list<Item> list, Args&&... args);
70 template <
typename ValueType>
73 struct HolderDeleter {
77 template <
typename ValueType>
78 friend ValueType*
AnyCast(AnyMovable*)
noexcept;
80 template <
typename ValueType>
81 friend const ValueType*
AnyCast(
const AnyMovable*)
noexcept;
83 std::unique_ptr<
HolderBase, HolderDeleter> content_;
87class BadAnyMovableCast
final :
public std::bad_any_cast {
89 const char* what()
const noexcept override;
94template <
typename ValueType>
95ValueType*
AnyCast(AnyMovable* operand)
noexcept;
99template <
typename ValueType>
100const ValueType*
AnyCast(
const AnyMovable* operand)
noexcept;
105template <
typename ValueType>
106ValueType
AnyCast(AnyMovable& operand);
111template <
typename ValueType>
112ValueType
AnyCast(
const AnyMovable& operand);
117template <
typename ValueType>
118ValueType
AnyCast(AnyMovable&& operand);
121 using DeleterType =
void (*)(
HolderBase&)
noexcept;
126template <
typename ValueType>
127struct AnyMovable::Holder
final :
public HolderBase {
128 static_assert(std::is_same_v<ValueType, std::decay_t<ValueType>>,
129 "The requested type can't be stored in an AnyMovable");
133 static void Deleter(
HolderBase& holder)
noexcept {
134 delete &
static_cast<Holder&>(holder);
137 template <
typename... Args>
138 static std::unique_ptr<
HolderBase, HolderDeleter> Make(Args&&... args) {
139 return std::unique_ptr<HolderBase, HolderDeleter>{
142 new Holder{{&Deleter}, ValueType(std::forward<Args>(args)...)}};
145 static ValueType* GetIf(
const AnyMovable* any)
noexcept {
146 return (any && any->content_ && any->content_->deleter == &Deleter)
147 ? &
static_cast<Holder&>(*any->content_).held
152template <
typename ValueType,
typename>
157 !std::is_same_v<AnyMovable*, std::decay_t<ValueType>> &&
158 !std::is_same_v<
const AnyMovable*, std::decay_t<ValueType>>,
159 "AnyMovable misuse detected: trying to wrap AnyMovable* in another "
160 "AnyMovable. The pointer was probably meant to be dereferenced.");
163template <
typename ValueType,
typename... Args>
164AnyMovable::
AnyMovable(std::in_place_type_t<ValueType> , Args&&... args)
167template <
typename ValueType,
typename Item,
typename... Args>
169 std::initializer_list<Item> list, Args&&... args)
172template <
typename ValueType>
173AnyMovable& AnyMovable::
operator=(ValueType&& rhs) {
174 *
this = AnyMovable(std::forward<ValueType>(rhs));
178template <
typename ValueType,
typename... Args>
179ValueType& AnyMovable::
Emplace(Args&&... args) {
180 content_ = Holder<ValueType>::Make(std::forward<Args>(args)...);
181 return static_cast<Holder<ValueType>&>(*content_).held;
184template <
typename ValueType,
typename Item,
typename... Args>
185ValueType& AnyMovable::
Emplace(std::initializer_list<Item> list,
187 content_ = Holder<ValueType>::Make(list, std::forward<Args>(args)...);
188 return static_cast<Holder<ValueType>&>(*content_).held;
191template <
typename ValueType>
192ValueType*
AnyCast(AnyMovable* operand)
noexcept {
193 return AnyMovable::Holder<ValueType>::GetIf(operand);
196template <
typename ValueType>
197const ValueType*
AnyCast(
const AnyMovable* operand)
noexcept {
198 return AnyMovable::Holder<ValueType>::GetIf(operand);
201template <
typename ValueType>
205 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
206 auto* result = AnyCast<NonRef>(&operand);
207 if (!result)
throw BadAnyMovableCast();
208 return static_cast<ValueType>(*result);
211template <
typename ValueType>
215 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
216 auto* result = AnyCast<NonRef>(&operand);
217 if (!result)
throw BadAnyMovableCast();
218 return static_cast<ValueType>(*result);
221template <
typename ValueType>
223 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
224 auto* result = AnyCast<NonRef>(&operand);
225 if (!result)
throw BadAnyMovableCast();
226 return static_cast<ValueType>(std::move(*result));