20 #include <type_traits> 28 const char*
what() const noexcept
override 30 return "bad any cast";
38 any() : vtable(nullptr)
43 any(
const any& rhs) : vtable(rhs.vtable)
53 any(
any&& rhs) noexcept : vtable(rhs.vtable)
57 rhs.vtable->move(rhs.storage, this->storage);
72 template <
typename ValueType,
typename =
typename std::enable_if<!
std::is_same<
73 typename std::decay<ValueType>::type,
any>::value>::type>
74 any(ValueType&& value)
76 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
77 "T shall satisfy the CopyConstructible requirements.");
78 this->construct(std::forward<ValueType>(value));
94 any(std::move(rhs)).
swap(*
this);
102 template <
typename ValueType,
typename =
typename std::enable_if<!
std::is_same<
103 typename std::decay<ValueType>::type,
any>::value>::type>
106 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
107 "T shall satisfy the CopyConstructible requirements.");
108 any(std::forward<ValueType>(value)).
swap(*
this);
117 this->vtable->destroy(storage);
118 this->vtable =
nullptr;
125 return this->vtable ==
nullptr;
129 const std::type_info&
type() const noexcept
131 return empty() ?
typeid(void) : this->vtable->type();
137 if (this->vtable != rhs.vtable)
139 any tmp(std::move(rhs));
142 rhs.vtable = this->vtable;
143 if (this->vtable !=
nullptr)
145 this->vtable->move(this->storage, rhs.storage);
150 this->vtable = tmp.
vtable;
151 if (tmp.
vtable !=
nullptr)
159 if (this->vtable !=
nullptr)
160 this->vtable->
swap(this->storage, rhs.storage);
168 typename std::aligned_storage<2 * sizeof(void*), std::alignment_of<void*>::value>::type;
181 const std::type_info& (*type)() noexcept;
200 template <
typename T>
203 static const std::type_info&
type() noexcept
211 delete reinterpret_cast<T*
>(storage.dynamic);
221 dest.dynamic = src.dynamic;
222 src.dynamic =
nullptr;
233 template <
typename T>
236 static const std::type_info&
type() noexcept
243 reinterpret_cast<T*
>(&storage.stack)->~T();
248 new (&dest.
stack) T(reinterpret_cast<const T&>(src.
stack));
255 new (&dest.stack) T(std::move(reinterpret_cast<T&>(src.stack)));
262 move(rhs, tmp_storage);
264 move(tmp_storage, lhs);
269 template <
typename T>
271 : std::integral_constant<
273 !(std::is_nothrow_move_constructible<T>::value
274 && sizeof(T) <= sizeof(storage_union::stack) &&
275 std::alignment_of<T>::value <=
276 std::alignment_of<storage_union::stack_storage_t>::value)>
281 template <typename T>
282 static vtable_type* vtable_for_type()
284 using VTableType = typename std::conditional<requires_allocation<T>::value,
285 vtable_dynamic<T>, vtable_stack<T>>::type;
286 static vtable_type table = {
287 VTableType::type, VTableType::destroy, VTableType::copy,
288 VTableType::move, VTableType::swap,
294 template <typename T>
295 friend const T* any_cast(const any* operand) noexcept;
296 template <typename T>
297 friend T* any_cast(any* operand) noexcept;
300 bool is_typed(const std::type_info& t) const
302 return is_same(this->type(), t);
311 static bool is_same(const std::type_info& a, const std::type_info& b)
313 #ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
321 template <typename T>
322 const T* cast() const noexcept
324 return requires_allocation<typename std::decay<T>::type>::value ?
325 reinterpret_cast<const T*>(storage.dynamic) :
326 reinterpret_cast<const T*>(&storage.stack);
330 template <typename T>
333 return requires_allocation<typename std::decay<T>::type>::value ?
334 reinterpret_cast<T*>(storage.dynamic) :
335 reinterpret_cast<T*>(&storage.stack);
339 storage_union storage;
342 template <typename ValueType, typename T>
343 typename std::enable_if<requires_allocation<T>::value>::type do_construct(ValueType&& value)
345 storage.dynamic = new T(std::forward<ValueType>(value));
348 template <typename ValueType, typename T>
349 typename std::enable_if<!requires_allocation<T>::value>::type do_construct(ValueType&& value)
351 new (&storage.stack) T(std::forward<ValueType>(value));
356 template <typename ValueType>
357 void construct(ValueType&& value)
359 using T = typename std::decay<ValueType>::type;
361 this->vtable = vtable_for_type<T>();
363 do_construct<ValueType, T>(std::forward<ValueType>(value));
369 template <
typename ValueType>
373 return std::move(*p);
376 template <
typename ValueType>
385 template <
typename ValueType>
389 any_cast<
typename std::add_const<typename std::remove_reference<ValueType>::type>::type>(
397 template <
typename ValueType>
400 auto p =
any_cast<
typename std::remove_reference<ValueType>::type>(&operand);
415 template <
typename ValueType>
418 #ifdef ANY_IMPL_ANY_CAST_MOVEABLE 420 using can_move = std::integral_constant<bool, std::is_move_constructible<ValueType>::value &&
421 !std::is_lvalue_reference<ValueType>::value>;
423 using can_move = std::false_type;
426 auto p =
any_cast<
typename std::remove_reference<ValueType>::type>(&operand);
429 return detail::any_cast_move_if_true<ValueType>(p, can_move());
434 template <
typename T>
437 if (operand ==
nullptr || !operand->is_typed(
typeid(T)))
440 return operand->cast<T>();
445 template <
typename T>
448 if (operand ==
nullptr || !operand->is_typed(
typeid(T)))
451 return operand->cast<T>();
void(* swap)(storage_union &lhs, storage_union &rhs) noexcept
Exchanges the storage between lhs and rhs.
static void copy(const storage_union &src, storage_union &dest)
static void destroy(storage_union &storage) noexcept
static void swap(storage_union &lhs, storage_union &rhs) noexcept
VTable for stack allocated storage.
any(const any &rhs)
Constructs an object of type any with an equivalent state as other.
bool empty() const noexcept
Returns true if *this has no contained object, otherwise false.
void(* copy)(const storage_union &src, storage_union &dest)
any & operator=(const any &rhs)
Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
void(* move)(storage_union &src, storage_union &dest) noexcept
typename std::aligned_storage< 2 *sizeof(void *), std::alignment_of< void * >::value >::type stack_storage_t
ValueType any_cast(const any &operand)
Performs *any_cast<add_const_t<remove_reference_t<ValueType>>>(&operand), or throws bad_any_cast on f...
void swap(linb::any &lhs, linb::any &rhs) noexcept
any()
Constructs an object of type any with an empty state.
~any()
Same effect as this->clear().
void destroy(routine_t id)
any & operator=(ValueType &&value)
VTable for dynamically allocated storage.
static void swap(storage_union &lhs, storage_union &rhs) noexcept
static const std::type_info & type() noexcept
static void move(storage_union &src, storage_union &dest) noexcept
static void copy(const storage_union &src, storage_union &dest)
Base VTable specification.
std::is_same< T, U > is_same
any & operator=(any &&rhs) noexcept
static void move(storage_union &src, storage_union &dest) noexcept
static void destroy(storage_union &storage) noexcept
void clear() noexcept
If not empty, destroys the contained object.
const char * what() const noexceptoverride
const std::type_info & type() const noexcept
If *this has a contained object of type T, typeid(T); otherwise typeid(void).
Whether the type T must be dynamically allocated or can be stored on the stack.
ValueType any_cast_move_if_true(typename std::remove_reference< ValueType >::type *p, std::false_type)
void swap(any &rhs) noexcept
Exchange the states of *this and rhs.
static const std::type_info & type() noexcept