29 #ifndef CDPL_BASE_ANY_HPP
30 #define CDPL_BASE_ANY_HPP
34 #include <type_traits>
66 Any() noexcept : vtable(
nullptr) {}
76 rhs.vtable->copy(rhs.storage, this->storage);
86 Any(
Any&& rhs) noexcept : vtable(rhs.vtable)
89 rhs.vtable->move(rhs.storage, this->storage);
112 template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
Any>::value>::type>
115 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
116 "ValueType shall satisfy CopyConstructible requirements.");
118 this->construct(std::forward<ValueType>(val));
128 Any(rhs).swap(*
this);
142 Any(std::move(rhs)).swap(*
this);
155 template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
Any>::value>::type>
158 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
159 "T shall satisfy CopyConstructible requirements.");
161 Any(std::forward<ValueType>(val)).swap(*
this);
172 this->vtable->destroy(storage);
173 this->vtable =
nullptr;
184 return (this->vtable ==
nullptr);
195 return (
isEmpty() ?
typeid(
void) : this->vtable->type());
205 if (this->vtable != rhs.vtable) {
206 Any tmp(std::move(rhs));
209 rhs.vtable = this->vtable;
211 if (this->vtable !=
nullptr) {
212 this->vtable->move(this->storage, rhs.storage);
217 this->vtable = tmp.vtable;
219 if (tmp.vtable !=
nullptr) {
220 tmp.vtable->move(tmp.storage, this->storage);
221 tmp.vtable =
nullptr;
225 if (this->vtable !=
nullptr)
226 this->vtable->swap(this->storage, rhs.storage);
236 template <
typename ValueType>
242 using T =
typename std::decay<ValueType>::type;
244 if (this->isTyped(
typeid(
T)))
245 return *this->cast<T>();
247 throw BadCast(std::string(
"Any: extraction of stored value of type '") + this->
getTypeID().name() +
248 std::string(
"' as type '") +
typeid(
T).name() +
"' not possible");
262 return this->vtable->data(this->storage);
269 using StackStorageT =
typename std::aligned_storage<2 *
sizeof(
void*), std::alignment_of<void*>::value>::type;
282 const std::type_info& (*type)() noexcept;
286 void (*destroy)(Storage&) noexcept;
290 void (*copy)(
const Storage& src, Storage& dest);
294 void (*move)(Storage& src, Storage& dest) noexcept;
297 void (*
swap)(Storage& lhs, Storage& rhs) noexcept;
299 const void* (*data)(
const Storage& storage)noexcept;
303 template <
typename T>
307 static const std::type_info& type() noexcept
312 static void destroy(Storage& storage) noexcept
315 delete reinterpret_cast<T*
>(storage.dynamic);
318 static void copy(
const Storage& src, Storage& dest)
320 dest.dynamic =
new T(*
reinterpret_cast<const T*
>(src.dynamic));
323 static void move(Storage& src, Storage& dest) noexcept
325 dest.dynamic = src.dynamic;
326 src.dynamic =
nullptr;
329 static void swap(Storage& lhs, Storage& rhs) noexcept
332 std::swap(lhs.dynamic, rhs.dynamic);
335 static const void* data(
const Storage& storage) noexcept
337 return storage.dynamic;
342 template <
typename T>
346 static const std::type_info& type() noexcept
351 static void destroy(Storage& storage) noexcept
353 reinterpret_cast<T*
>(&storage.stack)->~
T();
356 static void copy(
const Storage& src, Storage& dest)
358 new (&dest.stack)
T(
reinterpret_cast<const T&
>(src.stack));
361 static void move(Storage& src, Storage& dest) noexcept
365 new (&dest.stack)
T(std::move(
reinterpret_cast<T&
>(src.stack)));
369 static void swap(Storage& lhs, Storage& rhs) noexcept
373 move(rhs, tmp_storage);
375 move(tmp_storage, lhs);
378 static const void* data(
const Storage& storage) noexcept
380 return &storage.stack;
385 template <
typename T>
386 struct RequiresAlloc : std::integral_constant<bool,
387 !(std::is_nothrow_move_constructible<T>::value
388 && sizeof(T) <= sizeof(Storage::stack) && std::alignment_of<T>::value <= std::alignment_of<Storage::StackStorageT>::value)>
392 template <typename T>
393 static VTable* getVTableForType()
396 using VTableType = typename std::conditional<RequiresAlloc<T>::value, VTableDynamic<T>, VTableStack<T> >::type;
398 static VTable table = {
411 bool isTyped(const std::type_info& t) const
413 return (this->getTypeID() == t);
417 template <typename T>
418 const T* cast() const noexcept
420 return RequiresAlloc<T>::value ? reinterpret_cast<const T*>(storage.dynamic) :
421 reinterpret_cast<const T*>(&storage.stack);
424 template <typename ValueType, typename T>
425 typename std::enable_if<RequiresAlloc<T>::value>::type
426 doConstruct(ValueType&& value)
428 storage.dynamic = new T(std::forward<ValueType>(value));
431 template <typename ValueType, typename T>
432 typename std::enable_if<!RequiresAlloc<T>::value>::type
433 doConstruct(ValueType&& value)
435 new (&storage.stack) T(std::forward<ValueType>(value));
440 template <typename ValueType>
441 void construct(ValueType&& value)
443 using T = typename std::decay<ValueType>::type;
445 this->vtable = getVTableForType<T>();
447 doConstruct<ValueType, T>(std::forward<ValueType>(value));
476 #endif // CDPL_BASE_ANY_HPP