20 #include <type_traits>
29 const char* what()
const noexcept
override
31 return "bad any cast";
50 rhs.vtable->copy(rhs.storage, this->storage);
61 rhs.vtable->move(rhs.storage, this->storage);
76 template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
any>::value>
::type>
77 any(ValueType&& value)
79 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
80 "T shall satisfy the CopyConstructible requirements.");
81 this->construct(std::forward<ValueType>(value));
97 any(std::move(rhs)).swap(*
this);
105 template<typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
any>::value>
::type>
108 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
109 "T shall satisfy the CopyConstructible requirements.");
110 any(std::forward<ValueType>(value)).swap(*
this);
119 this->vtable->destroy(storage);
120 this->vtable =
nullptr;
127 return this->vtable ==
nullptr;
131 const std::type_info&
type() const noexcept
133 return empty()?
typeid(void) : this->vtable->type();
139 if(this->vtable != rhs.vtable)
141 any tmp(std::move(rhs));
144 rhs.vtable = this->vtable;
145 if(this->vtable !=
nullptr)
147 this->vtable->move(this->storage, rhs.storage);
152 this->vtable = tmp.vtable;
153 if(tmp.vtable !=
nullptr)
155 tmp.vtable->move(tmp.storage, this->storage);
156 tmp.vtable =
nullptr;
161 if(this->vtable !=
nullptr)
162 this->vtable->swap(this->storage, rhs.storage);
170 using stack_storage_t =
typename std::aligned_storage<2 *
sizeof(
void*), std::alignment_of<void*>::value>::
type;
173 stack_storage_t stack;
183 const std::type_info& (*type)() noexcept;
187 void(*destroy)(storage_union&) noexcept;
191 void(*copy)(
const storage_union& src, storage_union& dest);
195 void(*move)(storage_union& src, storage_union& dest) noexcept;
198 void(*
swap)(storage_union& lhs, storage_union& rhs) noexcept;
203 struct vtable_dynamic
205 static const std::type_info&
type() noexcept
210 static void destroy(storage_union& storage) noexcept
213 delete reinterpret_cast<T*
>(storage.dynamic);
216 static void copy(
const storage_union& src, storage_union& dest)
218 dest.dynamic =
new T(*
reinterpret_cast<const T*
>(src.dynamic));
221 static void move(storage_union& src, storage_union& dest) noexcept
223 dest.dynamic = src.dynamic;
224 src.dynamic =
nullptr;
227 static void swap(storage_union& lhs, storage_union& rhs) noexcept
230 std::swap(lhs.dynamic, rhs.dynamic);
238 static const std::type_info&
type() noexcept
243 static void destroy(storage_union& storage) noexcept
245 reinterpret_cast<T*
>(&storage.stack)->~T();
248 static void copy(
const storage_union& src, storage_union& dest)
250 new (&dest.stack) T(
reinterpret_cast<const T&
>(src.stack));
253 static void move(storage_union& src, storage_union& dest) noexcept
257 new (&dest.stack) T(std::move(
reinterpret_cast<T&
>(src.stack)));
261 static void swap(storage_union& lhs, storage_union& rhs) noexcept
263 std::swap(
reinterpret_cast<T&
>(lhs.stack),
reinterpret_cast<T&
>(rhs.stack));
269 struct requires_allocation :
270 std::integral_constant<bool,
271 !(std::is_nothrow_move_constructible<T>::value
272 && sizeof(T) <= sizeof(storage_union::stack)
273 && std::alignment_of<T>::value <= std::alignment_of<storage_union::stack_storage_t>::value)>
278 static vtable_type* vtable_for_type()
280 using VTableType = typename std::conditional<requires_allocation<T>::value, vtable_dynamic<T>, vtable_stack<T>>::type;
281 static vtable_type table = {
282 VTableType::type, VTableType::destroy,
283 VTableType::copy, VTableType::move,
291 friend const T* any_cast(const any* operand) noexcept;
293 friend T* any_cast(any* operand) noexcept;
296 bool is_typed(const std::type_info& t) const
298 return is_same(this->type(), t);
307 static bool is_same(const std::type_info& a, const std::type_info& b)
309 #ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
318 const T* cast() const noexcept
320 return requires_allocation<typename std::decay<T>::type>::value?
321 reinterpret_cast<const T*>(storage.dynamic) :
322 reinterpret_cast<const T*>(&storage.stack);
329 return requires_allocation<typename std::decay<T>::type>::value?
330 reinterpret_cast<T*>(storage.dynamic) :
331 reinterpret_cast<T*>(&storage.stack);
335 storage_union storage;
338 template<typename ValueType, typename T>
339 typename std::enable_if<requires_allocation<T>::value>::type
340 do_construct(ValueType&& value)
342 storage.dynamic = new T(std::forward<ValueType>(value));
345 template<typename ValueType, typename T>
346 typename std::enable_if<!requires_allocation<T>::value>::type
347 do_construct(ValueType&& value)
349 new (&storage.stack) T(std::forward<ValueType>(value));
354 template<typename ValueType>
355 void construct(ValueType&& value)
357 using T = typename std::decay<ValueType>::type;
359 this->vtable = vtable_for_type<T>();
361 do_construct<ValueType,T>(std::forward<ValueType>(value));
369 template<
typename ValueType>
370 inline ValueType any_cast_move_if_true(
typename std::remove_reference<ValueType>::type* p, std::true_type)
372 return std::move(*p);
375 template<
typename ValueType>
376 inline ValueType any_cast_move_if_true(
typename std::remove_reference<ValueType>::type* p, std::false_type)
383 template<
typename ValueType>
386 auto p = any_cast<typename std::add_const<typename std::remove_reference<ValueType>::type>
::type>(&operand);
392 template<
typename ValueType>
395 auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
396 if(p ==
nullptr)
throw bad_any_cast();
409 template<
typename ValueType>
412 #ifdef ANY_IMPL_ANY_CAST_MOVEABLE
414 using can_move = std::integral_constant<bool,
415 std::is_move_constructible<ValueType>::value
416 && !std::is_lvalue_reference<ValueType>::value>;
418 using can_move = std::false_type;
421 auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
422 if(p ==
nullptr)
throw bad_any_cast();
423 return detail::any_cast_move_if_true<ValueType>(p, can_move());
431 if(operand ==
nullptr || !operand->is_typed(
typeid(T)))
434 return operand->cast<T>();
442 if(operand ==
nullptr || !operand->is_typed(
typeid(T)))
445 return operand->cast<T>();
any & operator=(ValueType &&value)
Has the same effect as any(std::forward<ValueType>(value)).swap(*this).
Definition: any.hpp:106
void clear() noexcept
If not empty, destroys the contained object.
Definition: any.hpp:115
any()
Constructs an object of type any with an empty state.
Definition: any.hpp:39
any(any &&rhs) noexcept
Constructs an object of type any with a state equivalent to the original state of other.
Definition: any.hpp:56
any(const any &rhs)
Constructs an object of type any with an equivalent state as other.
Definition: any.hpp:45
void swap(any &rhs) noexcept
Exchange the states of *this and rhs.
Definition: any.hpp:137
friend const T * any_cast(const any *operand) noexcept
If operand != nullptr && operand->type() == typeid(ValueType), a pointer to the object contained by o...
Definition: any.hpp:429
bool empty() const noexcept
Returns true if *this has no contained object, otherwise false.
Definition: any.hpp:125
any & operator=(const any &rhs)
Has the same effect as any(rhs).swap(*this). No effects if an exception is thrown.
Definition: any.hpp:85
any & operator=(any &&rhs) noexcept
Has the same effect as any(std::move(rhs)).swap(*this).
Definition: any.hpp:95
any(ValueType &&value)
Constructs an object of type any that contains an object of type T direct-initialized with std::forwa...
Definition: any.hpp:77
const std::type_info & type() const noexcept
If *this has a contained object of type T, typeid(T); otherwise typeid(void).
Definition: any.hpp:131
~any()
Same effect as this->clear().
Definition: any.hpp:67