26#if !defined(__cpp_exceptions) && !defined(ANY_IMPL_NO_EXCEPTIONS) && !defined(ANY_IMPL_EXCEPTIONS)
27# define ANY_IMPL_NO_EXCEPTIONS
35#if !defined(__cpp_rtti) && !defined(ANY_IMPL_NO_RTTI) && !defined(ANY_IMPL_RTTI)
36# define ANY_IMPL_NO_RTTI
52 const char*
what() const noexcept
override
54 return "bad any cast";
73 rhs.vtable->copy(rhs.storage, this->storage);
84 rhs.vtable->move(rhs.storage, this->storage);
99 template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
any>::value>
::type>
102 static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
103 "T shall satisfy the CopyConstructible requirements.");
104 this->construct(std::forward<ValueType>(value));
110 any(rhs).swap(*
this);
120 any(std::move(rhs)).swap(*
this);
128 template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
any>::value>
::type>
131 static_assert(std::is_copy_constructible<typename std::decay<ValueType>::type>::value,
132 "T shall satisfy the CopyConstructible requirements.");
133 any(std::forward<ValueType>(value)).swap(*
this);
142 this->vtable->destroy(storage);
143 this->vtable =
nullptr;
150 return this->vtable ==
nullptr;
153#ifndef ANY_IMPL_NO_RTTI
155 const std::type_info&
type() const noexcept
157 return empty()?
typeid(void) : this->vtable->type();
164 if(this->vtable != rhs.vtable)
166 any tmp(std::move(rhs));
169 rhs.vtable = this->vtable;
170 if(this->vtable !=
nullptr)
172 this->vtable->move(this->storage, rhs.storage);
177 this->vtable = tmp.vtable;
178 if(tmp.vtable !=
nullptr)
180 tmp.vtable->move(tmp.storage, this->storage);
181 tmp.vtable =
nullptr;
186 if(this->vtable !=
nullptr)
187 this->vtable->swap(this->storage, rhs.storage);
195 using stack_storage_t =
typename std::aligned_storage<2 *
sizeof(
void*), std::alignment_of<void*>::value>::
type;
198 stack_storage_t stack;
207#ifndef ANY_IMPL_NO_RTTI
209 const std::type_info& (*type)()
noexcept;
214 void(*destroy)(storage_union&)
noexcept;
218 void(*copy)(
const storage_union& src, storage_union& dest);
222 void(*move)(storage_union& src, storage_union& dest)
noexcept;
225 void(*
swap)(storage_union& lhs, storage_union& rhs)
noexcept;
230 struct vtable_dynamic
232#ifndef ANY_IMPL_NO_RTTI
233 static const std::type_info&
type() noexcept
239 static void destroy(storage_union& storage)
noexcept
242 delete reinterpret_cast<T*
>(storage.dynamic);
245 static void copy(
const storage_union& src, storage_union& dest)
247 dest.dynamic =
new T(*
reinterpret_cast<const T*
>(src.dynamic));
250 static void move(storage_union& src, storage_union& dest)
noexcept
252 dest.dynamic = src.dynamic;
253 src.dynamic =
nullptr;
256 static void swap(storage_union& lhs, storage_union& rhs)
noexcept
267#ifndef ANY_IMPL_NO_RTTI
268 static const std::type_info&
type() noexcept
274 static void destroy(storage_union& storage)
noexcept
276 reinterpret_cast<T*
>(&storage.stack)->~T();
279 static void copy(
const storage_union& src, storage_union& dest)
281 new (&dest.stack) T(
reinterpret_cast<const T&
>(src.stack));
284 static void move(storage_union& src, storage_union& dest)
noexcept
288 new (&dest.stack) T(std::move(
reinterpret_cast<T&
>(src.stack)));
292 static void swap(storage_union& lhs, storage_union& rhs)
noexcept
294 storage_union tmp_storage;
295 move(rhs, tmp_storage);
297 move(tmp_storage, lhs);
303 struct requires_allocation :
304 std::integral_constant<bool,
305 !(std::is_nothrow_move_constructible<T>::value
306 && sizeof(T) <= sizeof(storage_union::stack)
307 && std::alignment_of<T>::value <= std::alignment_of<storage_union::stack_storage_t>::value)>
312 static vtable_type* vtable_for_type()
314 using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
315 static vtable_type table = {
316#ifndef ANY_IMPL_NO_RTTI
320 VTableType::copy, VTableType::move,
328 friend const T* any_cast(const any* operand) noexcept;
330 friend T* any_cast(any* operand) noexcept;
332#ifndef ANY_IMPL_NO_RTTI
334 bool is_typed(const std::type_info& t) const
336 return is_same(this->type(), t);
340#ifndef ANY_IMPL_NO_RTTI
347 static bool is_same(const std::type_info& a, const std::type_info& b)
349#ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
359 const T* cast() const noexcept
361 return requires_allocation<typename std::decay<T>::type>::value?
362 reinterpret_cast<const T*>(storage.dynamic) :
363 reinterpret_cast<const T*>(&storage.stack);
370 return requires_allocation<typename std::decay<T>::type>::value?
371 reinterpret_cast<T*>(storage.dynamic) :
372 reinterpret_cast<T*>(&storage.stack);
376 storage_union storage = { 0 };
379 template<typename ValueType, typename T>
380 typename std::enable_if<requires_allocation<T>::value>::type
381 do_construct(ValueType&& value)
383 storage.dynamic = new T(std::forward<ValueType>(value));
386 template<typename ValueType, typename T>
387 typename std::enable_if<!requires_allocation<T>::value>::type
388 do_construct(ValueType&& value)
390 new (&storage.stack) T(std::forward<ValueType>(value));
395 template<typename ValueType>
396 void construct(ValueType&& value)
398 using T = typename std::decay<ValueType>::type;
400 this->vtable = vtable_for_type<T>();
402 do_construct<ValueType,T>(std::forward<ValueType>(value));
410 template<
typename ValueType>
413 return std::move(*p);
416 template<
typename ValueType>
424template<
typename ValueType>
427 auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>
::type>(&operand);
428#ifndef ANY_IMPL_NO_EXCEPTIONS
435template<
typename ValueType>
438 auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
439#ifndef ANY_IMPL_NO_EXCEPTIONS
450template<
typename ValueType>
453 using can_move = std::integral_constant<bool,
454 std::is_move_constructible<ValueType>::value
455 && !std::is_lvalue_reference<ValueType>::value>;
457 auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
458#ifndef ANY_IMPL_NO_EXCEPTIONS
461 return detail::any_cast_move_if_true<ValueType>(p, can_move());
466template<
typename ValueType>
469 using T =
typename std::decay<ValueType>::type;
471#ifndef ANY_IMPL_NO_RTTI
472 if (operand && operand->is_typed(
typeid(T)))
474 if (operand && operand->vtable == any::vtable_for_type<T>())
476 return operand->cast<ValueType>();
483template<
typename ValueType>
486 using T =
typename std::decay<ValueType>::type;
488#ifndef ANY_IMPL_NO_RTTI
489 if (operand && operand->is_typed(
typeid(T)))
491 if (operand && operand->vtable == any::vtable_for_type<T>())
493 return operand->cast<ValueType>();
bool empty() const noexcept
Returns true if *this has no contained object, otherwise false.
any & operator=(any &&rhs) noexcept
any & operator=(ValueType &&value)
void clear() noexcept
If not empty, destroys the contained object.
void swap(any &rhs) noexcept
Exchange the states of *this and rhs.
const std::type_info & type() const noexcept
If *this has a contained object of type T, typeid(T); otherwise typeid(void).
any(const any &rhs)
Constructs an object of type any with an equivalent state as other.
any & operator=(const any &rhs)
Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
friend const T * any_cast(const any *operand) noexcept
any()
Constructs an object of type any with an empty state.
~any()
Same effect as this->clear().
const char * what() const noexcept override
ValueType any_cast_move_if_true(typename std::remove_reference< ValueType >::type *p, std::false_type)
void swap(keyple::core::util::cpp::any &lhs, keyple::core::util::cpp::any &rhs) noexcept