29 #ifndef CDPL_BASE_ANY_HPP
30 #define CDPL_BASE_ANY_HPP
35 #include <type_traits>
67 Any() noexcept : vtable(
nullptr) {}
77 rhs.vtable->copy(rhs.storage, this->storage);
87 Any(
Any&& rhs) noexcept : vtable(rhs.vtable)
90 rhs.vtable->move(rhs.storage, this->storage);
113 template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
Any>::value>::type>
116 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
117 "ValueType shall satisfy CopyConstructible requirements.");
119 this->construct(std::forward<ValueType>(val));
129 Any(rhs).swap(*
this);
143 Any(std::move(rhs)).swap(*
this);
156 template <typename ValueType, typename = typename std::enable_if<!std::is_same<typename std::decay<ValueType>::type,
Any>::value>::type>
159 static_assert(std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
160 "T shall satisfy CopyConstructible requirements.");
162 Any(std::forward<ValueType>(val)).swap(*
this);
173 this->vtable->destroy(storage);
174 this->vtable =
nullptr;
185 return (this->vtable ==
nullptr);
196 return (
isEmpty() ?
typeid(
void) : this->vtable->type());
206 if (this->vtable != rhs.vtable) {
207 Any tmp(std::move(rhs));
210 rhs.vtable = this->vtable;
212 if (this->vtable !=
nullptr) {
213 this->vtable->move(this->storage, rhs.storage);
218 this->vtable = tmp.vtable;
220 if (tmp.vtable !=
nullptr) {
221 tmp.vtable->move(tmp.storage, this->storage);
222 tmp.vtable =
nullptr;
226 if (this->vtable !=
nullptr)
227 this->vtable->swap(this->storage, rhs.storage);
237 template <
typename ValueType>
243 using T =
typename std::decay<ValueType>::type;
245 if (this->isTyped(
typeid(
T)))
246 return *this->cast<T>();
248 throw BadCast(std::string(
"Any: extraction of stored value of type '") + this->
getTypeID().name() +
249 std::string(
"' as type '") +
typeid(
T).name() +
"' not possible");
263 return this->vtable->data(this->storage);
270 using StackStorageT =
typename std::aligned_storage<2 *
sizeof(
void*), std::alignment_of<void*>::value>::type;
283 const std::type_info& (*type)() noexcept;
287 void (*destroy)(Storage&) noexcept;
291 void (*copy)(
const Storage& src, Storage& dest);
295 void (*move)(Storage& src, Storage& dest) noexcept;
298 void (*
swap)(Storage& lhs, Storage& rhs) noexcept;
300 const void* (*data)(
const Storage& storage)noexcept;
304 template <
typename T>
308 static const std::type_info& type() noexcept
313 static void destroy(Storage& storage) noexcept
316 delete reinterpret_cast<T*
>(storage.dynamic);
319 static void copy(
const Storage& src, Storage& dest)
321 dest.dynamic =
new T(*
reinterpret_cast<const T*
>(src.dynamic));
324 static void move(Storage& src, Storage& dest) noexcept
326 dest.dynamic = src.dynamic;
327 src.dynamic =
nullptr;
330 static void swap(Storage& lhs, Storage& rhs) noexcept
333 std::swap(lhs.dynamic, rhs.dynamic);
336 static const void* data(
const Storage& storage) noexcept
338 return storage.dynamic;
343 template <
typename T>
347 static const std::type_info& type() noexcept
352 static void destroy(Storage& storage) noexcept
354 reinterpret_cast<T*
>(&storage.stack)->~
T();
357 static void copy(
const Storage& src, Storage& dest)
359 new (&dest.stack)
T(
reinterpret_cast<const T&
>(src.stack));
362 static void move(Storage& src, Storage& dest) noexcept
366 new (&dest.stack)
T(std::move(
reinterpret_cast<T&
>(src.stack)));
370 static void swap(Storage& lhs, Storage& rhs) noexcept
374 move(rhs, tmp_storage);
376 move(tmp_storage, lhs);
379 static const void* data(
const Storage& storage) noexcept
381 return &storage.stack;
386 template <
typename T>
387 struct RequiresAlloc : std::integral_constant<bool,
388 !(std::is_nothrow_move_constructible<T>::value
389 && sizeof(T) <= sizeof(Storage::stack) && std::alignment_of<T>::value <= std::alignment_of<Storage::StackStorageT>::value)>
393 template <typename T>
394 static VTable* getVTableForType()
397 using VTableType = typename std::conditional<RequiresAlloc<T>::value, VTableDynamic<T>, VTableStack<T> >::type;
399 static VTable table = {
412 bool isTyped(const std::type_info& t) const
414 if (&this->getTypeID() == &t)
423 return (std::strcmp(this->getTypeID().name(), t.name()) == 0);
427 template <typename T>
428 const
T* cast() const noexcept
430 return RequiresAlloc<T>::value ?
reinterpret_cast<const T*
>(storage.dynamic) :
431 reinterpret_cast<const T*
>(&storage.stack);
434 template <
typename ValueType,
typename T>
435 typename std::enable_if<RequiresAlloc<T>::value>::type
436 doConstruct(ValueType&& value)
438 storage.dynamic =
new T(std::forward<ValueType>(value));
441 template <
typename ValueType,
typename T>
442 typename std::enable_if<!RequiresAlloc<T>::value>::type
443 doConstruct(ValueType&& value)
445 new (&storage.stack)
T(std::forward<ValueType>(value));
450 template <
typename ValueType>
451 void construct(ValueType&& value)
453 using T =
typename std::decay<ValueType>::type;
455 this->vtable = getVTableForType<T>();
457 doConstruct<ValueType, T>(std::forward<ValueType>(value));
465 inline const Any& Any::getData<Any>()
const
Definition of exception classes.
A safe, type checked container for arbitrary data of variable type.
Definition: Any.hpp:60
const ValueType & getData() const
Returns a const reference to the stored object of type ValueType, or *this if ValueType is Any.
Definition: Any.hpp:238
void swap(Any &rhs) noexcept
Exchange the states of *this and rhs.
Definition: Any.hpp:204
~Any()
Destructor.
Definition: Any.hpp:100
Any & operator=(const Any &rhs)
Has the same effect as Any(rhs).swap(*this). No effects if an exception is thrown.
Definition: Any.hpp:127
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:157
Any(Any &&rhs) noexcept
Constructs an object of type Any with a state equivalent to the original state of rhs.
Definition: Any.hpp:87
Any(const Any &rhs)
Constructs an object of type Any with an equivalent state as rhs.
Definition: Any.hpp:73
void clear() noexcept
If not empty, destroys the contained object.
Definition: Any.hpp:170
const void * getDataPointer() const noexcept
Returns a raw pointer to the memory occupied by the stored data.
Definition: Any.hpp:258
Any & operator=(Any &&rhs) noexcept
Has the same effect as Any(std::move(rhs)).swap(*this).
Definition: Any.hpp:141
const std::type_info & getTypeID() const noexcept
Returns information about the type of the stored object.
Definition: Any.hpp:194
Any() noexcept
Constructs an object of type Any with an empty state.
Definition: Any.hpp:67
bool isEmpty() const noexcept
Tells whether the Any instance stores any data.
Definition: Any.hpp:183
Any(ValueType &&val)
Constructs an object of type Any that contains an object of type ValueType direct-initialized with st...
Definition: Any.hpp:114
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.