7#include <initializer_list>
12USERVER_NAMESPACE_BEGIN
24class AnyMovable
final {
31 AnyMovable& operator=(AnyMovable&&)
noexcept =
default;
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) {
137 return std::unique_ptr<HolderBase, HolderDeleter>{
140 new Holder{{&Deleter}, ValueType(std::forward<Args>(args)...)}};
143 static ValueType* GetIf(
const AnyMovable* any)
noexcept {
144 return (any && any->content_ && any->content_->deleter == &Deleter) ? &
static_cast<Holder&>(*any->content_).held
149template <
typename ValueType,
typename>
153 !std::is_same_v<AnyMovable*, std::decay_t<ValueType>> &&
154 !std::is_same_v<
const AnyMovable*, std::decay_t<ValueType>>,
155 "AnyMovable misuse detected: trying to wrap AnyMovable* in another "
156 "AnyMovable. The pointer was probably meant to be dereferenced."
160template <
typename ValueType,
typename... Args>
161AnyMovable::
AnyMovable(std::in_place_type_t<ValueType> , Args&&... args)
164template <
typename ValueType,
typename Item,
typename... Args>
165AnyMovable::
AnyMovable(std::in_place_type_t<ValueType> , std::initializer_list<Item> list, Args&&... args)
168template <
typename ValueType>
169AnyMovable& AnyMovable::
operator=(ValueType&& rhs) {
170 *
this = AnyMovable(std::forward<ValueType>(rhs));
174template <
typename ValueType,
typename... Args>
175ValueType& AnyMovable::
Emplace(Args&&... args) {
176 content_ = Holder<ValueType>::Make(std::forward<Args>(args)...);
177 return static_cast<Holder<ValueType>&>(*content_).held;
180template <
typename ValueType,
typename Item,
typename... Args>
181ValueType& AnyMovable::
Emplace(std::initializer_list<Item> list, Args&&... args) {
182 content_ = Holder<ValueType>::Make(list, std::forward<Args>(args)...);
183 return static_cast<Holder<ValueType>&>(*content_).held;
186template <
typename ValueType>
187ValueType*
AnyCast(AnyMovable* operand)
noexcept {
188 return AnyMovable::Holder<ValueType>::GetIf(operand);
191template <
typename ValueType>
192const ValueType*
AnyCast(
const AnyMovable* operand)
noexcept {
193 return AnyMovable::Holder<ValueType>::GetIf(operand);
196template <
typename ValueType>
200 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
201 auto* result = AnyCast<NonRef>(&operand);
202 if (!result)
throw BadAnyMovableCast();
203 return static_cast<ValueType>(*result);
206template <
typename ValueType>
210 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
211 auto* result = AnyCast<NonRef>(&operand);
212 if (!result)
throw BadAnyMovableCast();
213 return static_cast<ValueType>(*result);
216template <
typename ValueType>
218 using NonRef = std::remove_cv_t<std::remove_reference_t<ValueType>>;
219 auto* result = AnyCast<NonRef>(&operand);
220 if (!result)
throw BadAnyMovableCast();
221 return static_cast<ValueType>(std::move(*result));