47 #ifndef OMEGA_H_ANY_HPP
48 #define OMEGA_H_ANY_HPP
50 #include <Omega_h_fail.hpp>
52 #include <type_traits>
60 const char* what()
const noexcept
override;
64 #pragma GCC diagnostic push
65 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
71 any() : vtable(nullptr) {}
74 any(
const any& rhs) : vtable(rhs.vtable) {
76 rhs.vtable->copy(rhs.storage, this->storage);
82 any(
any&& rhs) noexcept : vtable(rhs.vtable) {
84 rhs.vtable->move(rhs.storage, this->storage);
98 template <
typename ValueType,
99 typename =
typename std::enable_if<!std::is_same<
100 typename std::decay<ValueType>::type,
any>::value>
::type>
103 std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
104 "T shall satisfy the CopyConstructible requirements.");
105 this->construct(std::forward<ValueType>(value));
111 any(rhs).swap(*
this);
120 any(std::move(rhs)).swap(*
this);
130 template <
typename ValueType,
131 typename =
typename std::enable_if<!std::is_same<
132 typename std::decay<ValueType>::type,
any>::value>
::type>
135 std::is_copy_constructible<
typename std::decay<ValueType>::type>::value,
136 "T shall satisfy the CopyConstructible requirements.");
137 any(std::forward<ValueType>(value)).swap(*
this);
144 this->vtable->destroy(storage);
145 this->vtable =
nullptr;
150 bool empty() const noexcept {
return this->vtable ==
nullptr; }
154 const std::type_info&
type() const noexcept {
155 return empty() ?
typeid(void) : this->vtable->type();
160 if (this->vtable != rhs.vtable) {
161 any tmp(std::move(rhs));
164 rhs.vtable = this->vtable;
165 if (this->vtable !=
nullptr) {
166 this->vtable->move(this->storage, rhs.storage);
171 this->vtable = tmp.vtable;
172 if (tmp.vtable !=
nullptr) {
173 tmp.vtable->move(tmp.storage, this->storage);
174 tmp.vtable =
nullptr;
178 if (this->vtable !=
nullptr)
179 this->vtable->swap(this->storage, rhs.storage);
184 union storage_union {
185 using stack_storage_t =
typename std::aligned_storage<2 *
sizeof(
void*),
186 std::alignment_of<void*>::value>::
type;
189 stack_storage_t stack;
198 const std::type_info& (*type)() noexcept;
203 void (*destroy)(storage_union&) noexcept;
208 void (*copy)(
const storage_union& src, storage_union& dest);
213 void (*move)(storage_union& src, storage_union& dest) noexcept;
216 void (*
swap)(storage_union& lhs, storage_union& rhs) noexcept;
220 template <
typename T>
221 struct vtable_dynamic {
222 static const std::type_info&
type() noexcept {
return typeid(T); }
224 static void destroy(storage_union& storage) noexcept {
226 delete reinterpret_cast<T*
>(storage.dynamic);
229 static void copy(
const storage_union& src, storage_union& dest) {
230 dest.dynamic =
new T(*
reinterpret_cast<const T*
>(src.dynamic));
233 static void move(storage_union& src, storage_union& dest) noexcept {
234 dest.dynamic = src.dynamic;
235 src.dynamic =
nullptr;
238 static void swap(storage_union& lhs, storage_union& rhs) noexcept {
240 std::swap(lhs.dynamic, rhs.dynamic);
245 template <
typename T>
246 struct vtable_stack {
247 static const std::type_info&
type() noexcept {
return typeid(T); }
249 static void destroy(storage_union& storage) noexcept {
250 reinterpret_cast<T*
>(&storage.stack)->~T();
253 static void copy(
const storage_union& src, storage_union& dest) {
254 new (&dest.stack) T(
reinterpret_cast<const T&
>(src.stack));
257 static void move(storage_union& src, storage_union& dest) noexcept {
260 new (&dest.stack) T(std::move(
reinterpret_cast<T&
>(src.stack)));
264 static void swap(storage_union& lhs, storage_union& rhs) noexcept {
266 reinterpret_cast<T&
>(lhs.stack),
reinterpret_cast<T&
>(rhs.stack));
272 template <
typename T>
273 struct requires_allocation
274 : std::integral_constant<bool,
275 !(std::is_nothrow_move_constructible<T>::value
277 && sizeof(T) <= sizeof(storage_union::stack) &&
278 std::alignment_of<T>::value <=
279 std::alignment_of<storage_union::stack_storage_t>::value)> {
283 template <typename T>
284 static vtable_type* vtable_for_type() {
285 using VTableType = typename std::conditional<requires_allocation<T>::value,
286 vtable_dynamic<T>, vtable_stack<T>>::type;
287 static vtable_type table = {
298 template <typename T>
299 friend const T* any_cast(const any* operand) noexcept;
300 template <typename T>
301 friend T* any_cast(any* operand) noexcept;
304 bool is_typed(const std::type_info& t) const {
305 return is_same(this->type(), t);
314 static bool is_same(const std::type_info& a, const std::type_info& b) {
315 #ifdef ANY_IMPL_FAST_TYPE_INFO_COMPARE
323 template <typename T>
324 const T* cast() const noexcept {
325 return requires_allocation<typename std::decay<T>::type>::value
326 ? reinterpret_cast<const T*>(storage.dynamic)
327 : reinterpret_cast<const T*>(&storage.stack);
331 template <typename T>
333 return requires_allocation<typename std::decay<T>::type>::value
334 ? reinterpret_cast<T*>(storage.dynamic)
335 : reinterpret_cast<T*>(&storage.stack);
339 storage_union storage;
342 template <typename ValueType, typename T>
343 typename std::enable_if<requires_allocation<T>::value>::type do_construct(
345 storage.dynamic = new T(std::forward<ValueType>(value));
348 template <typename ValueType, typename T>
349 typename std::enable_if<!requires_allocation<T>::value>::type do_construct(
351 new (&storage.stack) T(std::forward<ValueType>(value));
357 template <typename ValueType>
358 void construct(ValueType&& value) {
359 using T = typename std::decay<ValueType>::type;
361 this->vtable = vtable_for_type<T>();
363 do_construct<ValueType, T>(std::forward<ValueType>(value));
368 #pragma GCC diagnostic pop
372 template <
typename ValueType>
373 inline ValueType any_cast_move_if_true(
374 typename std::remove_reference<ValueType>::type* p, std::true_type) {
375 return std::move(*p);
378 template <
typename ValueType>
379 inline ValueType any_cast_move_if_true(
380 typename std::remove_reference<ValueType>::type* p, std::false_type) {
387 template <
typename ValueType>
389 auto p =
any_cast<
typename std::add_const<
390 typename std::remove_reference<ValueType>::type>
::type>(&operand);
397 template <
typename ValueType>
399 auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
415 template <
typename ValueType>
418 using can_move = std::integral_constant<bool,
419 std::is_move_constructible<ValueType>::value &&
420 !std::is_lvalue_reference<ValueType>::value>;
422 auto p = any_cast<typename std::remove_reference<ValueType>::type>(&operand);
424 return detail::any_cast_move_if_true<ValueType>(p, can_move());
429 template <
typename T>
431 if (operand ==
nullptr || !operand->is_typed(
typeid(T)))
434 return operand->cast<T>();
439 template <
typename T>
441 if (operand ==
nullptr || !operand->is_typed(
typeid(T)))
444 return operand->cast<T>();
447 template <
typename T>
448 T&& move_value(
any& a) {
450 auto value_ptr = any_cast<T>(any_ptr);
451 OMEGA_H_CHECK(value_ptr !=
nullptr);
452 return std::move(*value_ptr);
Definition: Omega_h_any.hpp:68
any()
Constructs an object of type any with an empty state.
Definition: Omega_h_any.hpp:71
any & operator=(any &&rhs) noexcept
Definition: Omega_h_any.hpp:119
~any()
Same effect as this->clear().
Definition: Omega_h_any.hpp:90
void swap(any &rhs) noexcept
Exchange the states of *this and rhs.
Definition: Omega_h_any.hpp:159
friend const T * any_cast(const any *operand) noexcept
Definition: Omega_h_any.hpp:430
any(ValueType &&value)
Definition: Omega_h_any.hpp:101
any & operator=(ValueType &&value)
Definition: Omega_h_any.hpp:133
any(any &&rhs) noexcept
Definition: Omega_h_any.hpp:82
void clear() noexcept
If not empty, destroys the contained object.
Definition: Omega_h_any.hpp:142
const std::type_info & type() const noexcept
Definition: Omega_h_any.hpp:154
any(const any &rhs)
Constructs an object of type any with an equivalent state as other.
Definition: Omega_h_any.hpp:74
bool empty() const noexcept
Returns true if *this has no contained object, otherwise false.
Definition: Omega_h_any.hpp:150
any & operator=(const any &rhs)
Definition: Omega_h_any.hpp:110
Definition: Omega_h_any.hpp:58
Definition: amr_mpi_test.cpp:6