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));
Definition of exception classes.
A safe, type checked container for arbitrary data of variable type.
Definition: Any.hpp:59
const ValueType & getData() const
Returns a const reference to the stored object of type ValueType, or *this if ValueType is Any.
Definition: Any.hpp:237
void swap(Any &rhs) noexcept
Exchange the states of *this and rhs.
Definition: Any.hpp:203
~Any()
Destructor.
Definition: Any.hpp:99
Any & operator=(const Any &rhs)
Has the same effect as Any(rhs).swap(*this). No effects if an exception is thrown.
Definition: Any.hpp:126
Any & operator=(ValueType &&val)
Has the same effect as Any(std::forward<ValueType>(val)).swap(*this). No effect if a exception is thr...
Definition: Any.hpp:156
Any(Any &&rhs) noexcept
Constructs an object of type Any with a state equivalent to the original state of rhs.
Definition: Any.hpp:86
Any(const Any &rhs)
Constructs an object of type Any with an equivalent state as rhs.
Definition: Any.hpp:72
void clear() noexcept
If not empty, destroys the contained object.
Definition: Any.hpp:169
const void * getDataPointer() const noexcept
Returns a raw pointer to the memory occupied by the stored data.
Definition: Any.hpp:257
Any & operator=(Any &&rhs) noexcept
Has the same effect as Any(std::move(rhs)).swap(*this).
Definition: Any.hpp:140
const std::type_info & getTypeID() const noexcept
Returns information about the type of the stored object.
Definition: Any.hpp:193
Any() noexcept
Constructs an object of type Any with an empty state.
Definition: Any.hpp:66
bool isEmpty() const noexcept
Tells whether the Any instance stores any data.
Definition: Any.hpp:182
Any(ValueType &&val)
Constructs an object of type Any that contains an object of type ValueType direct-initialized with st...
Definition: Any.hpp:113
Thrown to indicate that a cast or conversion from a given source type to a requested target type is n...
Definition: Base/Exceptions.hpp:191
constexpr unsigned int T
Specifies Hydrogen (Tritium).
Definition: AtomType.hpp:67
The namespace of the Chemical Data Processing Library.