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>
64 template <
typename ValueType,
typename Item,
typename... Args>
65 void 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>
180 content_ = Holder<ValueType>::Make(std::forward<Args>(args)...);
183template <
typename ValueType,
typename Item,
typename... Args>
184void AnyMovable::
Emplace(std::initializer_list<Item> list, Args&&... args) {
185 content_ = Holder<ValueType>::Make(list, std::forward<Args>(args)...);
188template <
typename ValueType>
189ValueType*
AnyCast(AnyMovable* operand)
noexcept {
190 return AnyMovable::Holder<ValueType>::GetIf(operand);
193template <
typename ValueType>
194const ValueType*
AnyCast(
const AnyMovable* operand)
noexcept {
195 return AnyMovable::Holder<ValueType>::GetIf(operand);
198template <
typename ValueType>
202 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
203 auto* result = AnyCast<NonRef>(&operand);
204 if (!result)
throw BadAnyMovableCast();
205 return static_cast<ValueType>(*result);
208template <
typename ValueType>
212 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
213 auto* result = AnyCast<NonRef>(&operand);
214 if (!result)
throw BadAnyMovableCast();
215 return static_cast<ValueType>(*result);
218template <
typename ValueType>
220 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
221 auto* result = AnyCast<NonRef>(&operand);
222 if (!result)
throw BadAnyMovableCast();
223 return static_cast<ValueType>(std::move(*result));