36#include <initializer_list>
45#ifndef ANY_ALWAYS_INLINE
47#define ANY_ALWAYS_INLINE inline __attribute__((__visibility__("hidden"), __always_inline__))
49#define ANY_ALWAYS_INLINE inline
53#ifndef ANY_ALWAYS_INLINE
55#define ANY_ALWAYS_INLINE inline __forceinline
57#define ANY_ALWAYS_INLINE inline
65#define ANY_USE_TYPEINFO 0
71#define ANY_USE_EXCEPTIONS 0
74#ifndef ANY_USE_SMALL_MEMCPY_STRATEGY
75#define ANY_USE_SMALL_MEMCPY_STRATEGY 1
78#define ANY_USE(FEATURE) (defined ANY_USE_##FEATURE && ANY_USE_##FEATURE)
83class bad_any_cast :
public std::bad_cast { };
106using StorageBuffer = std::aligned_storage_t<StorageBufferSize, std::alignment_of_v<void*>>;
110 std::bool_constant<
sizeof(T) <=
sizeof(
StorageBuffer) && std::alignment_of_v<StorageBuffer> % std::alignment_of_v<T> == 0>;
141static constexpr void* void_get(Storage* s,
void const* info) {
146static constexpr void void_copy(Storage* dst, Storage
const* src) { }
149static constexpr void void_move(Storage* dst, Storage* src) { }
152static constexpr void void_drop(Storage* s) { }
169 void const*
type =
static_cast<void const*
>(&
typeid(void));
171 void const*
type = fallback_typeid<void>();
177#if ANY_USE_SMALL_MEMCPY_STRATEGY
178 template<
class X = T,
class... Args, std::enable_if_t<IsStorageBufferSized<X> && std::is_trivially_copyable_v<X>,
int> = 0>
180 X v(std::forward<Args>(args)...);
181 memcpy(&s->
buf,
static_cast<void*
>(&v),
sizeof(
X));
182 return *(
static_cast<X*
>(
static_cast<void*
>(&s->
buf)));
185 template<
class X = T,
class... Args,
186 std::enable_if_t<IsStorageBufferSized<X> && !std::is_trivially_copyable_v<X> && std::is_nothrow_move_constructible_v<X>,
189 return *(::new(
static_cast<void*
>(&s->
buf))
X(std::forward<Args>(args)...));
192 template<
class X = T,
class... Args,
193 std::enable_if_t<IsStorageBufferSized<X> && std::is_nothrow_move_constructible_v<X>,
int> = 0>
195 return *(::new(
static_cast<void*
>(&s->
buf))
X(std::forward<Args>(args)...));
205 template<
class X = T>
208 return *(
static_cast< std::type_info const*
>(id)) ==
typeid(
X);
210 return (
id &&
id == fallback_typeid<X>());
217 template<
class X = T, std::enable_if_t<std::is_same_v<X,
void>,
int> = 0>
222 template<
class X = T, std::enable_if_t<IsStorageBufferSized<X>,
int> = 0>
224 if(compare_typeid<X>(type)) {
225 return static_cast<void*
>(&s->buf);
233 template<
class X = T, std::enable_if_t<std::is_same_v<X,
void>,
int> = 0>
236#if ANY_USE_SMALL_MEMCPY_STRATEGY
237 template<
class X = T, std::enable_if_t<IsStorageBufferSized<X> && std::is_trivially_copyable_v<X>,
int> = 0>
239 memcpy(
static_cast<void*
>(&dst->buf),
static_cast<void*
>(
const_cast<StorageBuffer*
>(&src->buf)),
sizeof(
X));
242 template<
class X =
T,
243 std::enable_if_t<IsStorageBufferSized<X> && !std::is_trivially_copyable_v<X> && std::is_nothrow_move_constructible_v<X>,
246 AnyTraits::make(dst, std::in_place_type_t<X>(), *
static_cast<X const*
>(
static_cast<void const*
>(&src->buf)));
249 template<
class X = T, std::enable_if_t<IsStorageBufferSized<X> && std::is_nothrow_move_constructible_v<X>,
int> = 0>
251 AnyTraits::make(dst, std::in_place_type_t<X>(), *
static_cast<X const*
>(
static_cast<void const*
>(&src->buf)));
258#if ANY_USE_SMALL_MEMCPY_STRATEGY
259 template<
class X = T, std::enable_if_t<std::is_same_v<X,
void>,
int> = 0>
262 template<
class X = T, std::enable_if_t<IsStorageBufferSized<X>,
int> = 0>
264 memcpy(
static_cast<void*
>(&dst->buf),
static_cast<void*
>(
const_cast<StorageBuffer*
>(&src->buf)),
sizeof(
X));
267 template<
class X = T, std::enable_if_t<IsStorageBufferSized<X>,
int> = 0>
269 AnyTraits::make(dst, std::in_place_type_t<X>(), std::move(*
static_cast<X const*
>(
static_cast<void const*
>(&src->buf))));
276 template<
class X = T, std::enable_if_t<std::is_same_v<X,
void>,
int> = 0>
279 template<
class X = T, std::enable_if_t<std::is_trivially_destructible_v<X>,
int> = 0>
282 template<
class X = T, std::enable_if_t<IsStorageBufferSized<X> && !std::is_trivially_destructible_v<X>,
int> = 0>
284 X& t = *
static_cast<X*
>(
static_cast<void*
>(
const_cast<StorageBuffer*
>(&s->buf)));
300template<
class V,
class T = std::decay_t<V>>
301using IsAnyConstructible_ = std::bool_constant<!std::is_same_v<T, Any> && !IsInPlaceType<V> && std::is_copy_constructible_v<T>>;
306template<
class T,
class U,
class... Args>
308 std::bool_constant<std::is_constructible_v<T, std::initializer_list<U>&, Args...> && std::is_copy_constructible_v<T>>;
310template<
class T,
class U,
class... Args>
315 constexpr Any() noexcept : actions(VoidAnyActions) { }
317 template<
class V,
class T = std::decay_t<V>, std::enable_if_t<IsAnyConstructible<V>,
int> = 0>
322 template<
class V,
class... Args,
class T = std::decay_t<V>, std::enable_if_t<IsAnyConstructible<T>,
int> = 0>
323 explicit Any(std::in_place_type_t<V> vtype, Args&&... args) : actions(&
AnyTraits<T>::actions) {
327 template<
class V,
class U,
class... Args,
class T = std::decay_t<V>,
329 explicit Any(std::in_place_type_t<V> vtype, std::initializer_list<U> list, Args&&... args) : actions(&
AnyTraits<T>::actions) {
333 Any(
Any const& other) : actions(other.actions) {
334 actions->
copy(&storage, &other.storage);
337 Any(
Any&& other) noexcept : actions(other.actions) {
338 actions->
move(&storage, &other.storage);
339 other.actions = VoidAnyActions;
344 actions->
drop(&storage);
345 actions = other.actions;
346 actions->
copy(&storage, &other.storage);
353 actions->
drop(&storage);
354 actions = other.actions;
355 actions->
move(&storage, &other.storage);
356 other.actions = VoidAnyActions;
361 template<
class V,
class T = std::decay_t<V>, std::enable_if_t<IsAnyConstructible<T>,
int> = 0>
363 *
this =
Any(std::forward<V>(v));
368 actions->
drop(&storage);
371 template<
class V,
class... Args,
class T = std::decay_t<V>,
372 std::enable_if_t<std::is_constructible_v<T, Args...> && std::is_copy_constructible_v<T>,
int> = 0>
374 actions->
drop(&storage);
376 return AnyTraits<T>::make(&storage, std::in_place_type_t<T>(), std::forward<Args>(args)...);
379 template<
class V,
class U,
class... Args,
class T = std::decay_t<V>,
381 T&
emplace(std::initializer_list<U> list, Args&&... args) {
384 return AnyTraits<T>::make(&storage, std::in_place_type_t<T>(), V{list, std::forward<Args>(args)...});
389 actions->
drop(&storage);
390 actions = VoidAnyActions;
402 rhs.actions->
move(&tmp.storage, &rhs.storage);
403 actions->
move(&rhs.storage, &storage);
404 rhs.actions->move(&storage, &tmp.storage);
407 tmp.actions = rhs.actions;
408 rhs.actions = actions;
409 actions = tmp.actions;
414 return (actions != VoidAnyActions) ==
B;
419 return has_value<true>();
423 std::type_info
const& type() const noexcept {
424 return *
static_cast< std::type_info const*
>(actions->
type);
428 template<
typename CHECK_TYPE>
431 return typeid(CHECK_TYPE) == *
static_cast< std::type_info const*
>(actions->
type);
433 return (actions->
type == fallback_typeid<CHECK_TYPE>());
438 friend std::remove_cv_t<std::remove_reference_t<V>>*
any_cast(
Any* a)
noexcept;
442 static constexpr AnyActions const*
const VoidAnyActions = &_VoidAnyActions;
453template<
class T,
class... Args>
455 return Any(std::in_place_type<T>, std::forward<Args>(args)...);
458template<
class T,
class U,
class... Args>
460 return Any(std::in_place_type<T>, il, std::forward<Args>(args)...);
463template<
class V,
class T = std::remove_cv_t<std::remove_reference_t<V>>,
464 std::enable_if_t<std::is_constructible<V, T const&>{},
int> = 0>
466 auto tmp = any_cast<std::add_const_t<T>>(&a);
468 handle_bad_any_cast();
470 return static_cast<V
>(*tmp);
473template<
class V,
class T = std::remove_cv_t<std::remove_reference_t<V>>,
474 std::enable_if_t<std::is_constructible<V, T const&>{},
int> = 0>
476 auto tmp = any_cast<T>(&a);
478 handle_bad_any_cast();
480 return static_cast<V
>(*tmp);
483template<
class V,
class T = std::remove_cv_t<std::remove_reference_t<V>>,
484 std::enable_if_t<std::is_constructible<V, T const&>{},
int> = 0>
486 auto tmp = any_cast<T>(&a);
488 handle_bad_any_cast();
490 return static_cast<V
>(std::move(*tmp));
493template<
class V,
class T = std::remove_cv_t<std::remove_reference_t<V>>>
495 return any_cast<V>(
const_cast<Any*
>(a));
499std::remove_cv_t<std::remove_reference_t<V>>*
any_cast(
Any* a)
noexcept {
500 using T = std::remove_cv_t<std::remove_reference_t<V>>;
501 using U = std::decay_t<V>;
502 if(a && a->has_value()) {
503 void* p = a->actions->get(&a->storage,
510 return (std::is_function<V>{}) ?
nullptr :
static_cast<T*
>(p);
Any(Any &&other) noexcept
Any(std::in_place_type_t< V > vtype, std::initializer_list< U > list, Args &&... args)
Any & operator=(Any &&other) noexcept
ANY_ALWAYS_INLINE bool holds_type() const noexcept
ANY_ALWAYS_INLINE bool has_value() const noexcept
T & emplace(Args &&... args)
ANY_ALWAYS_INLINE void reset()
ANY_ALWAYS_INLINE bool has_value() const noexcept
T & emplace(std::initializer_list< U > list, Args &&... args)
ANY_ALWAYS_INLINE void swap(Any &rhs) noexcept
Any(std::in_place_type_t< V > vtype, Args &&... args)
Any & operator=(Any const &other)
#define ANY_ALWAYS_INLINE
std::bool_constant< std::is_constructible_v< T, std::initializer_list< U > &, Args... > &&std::is_copy_constructible_v< T > > IsAnyInitializerListConstructible_
std::bool_constant< sizeof(T)<=sizeof(StorageBuffer) &&std::alignment_of_v< StorageBuffer > % std::alignment_of_v< T >==0 > IsStorageBufferSized_
ANY_ALWAYS_INLINE constexpr void const * fallback_typeid()
constexpr size_t StorageBufferSize
constexpr bool IsAnyConstructible
constexpr bool IsInPlaceType
ANY_ALWAYS_INLINE void swap(Any &lhs, Any &rhs) noexcept
std::aligned_storage_t< StorageBufferSize, std::alignment_of_v< void * > > StorageBuffer
std::bool_constant<!std::is_same_v< T, Any > &&!IsInPlaceType< V > &&std::is_copy_constructible_v< T > > IsAnyConstructible_
constexpr bool IsAnyInitializerListConstructible
constexpr bool IsStorageBufferSized
ANY_ALWAYS_INLINE Any make_any(Args &&... args)
void *(*)(Storage *s, void const *type) Get
constexpr AnyActions(Get g, Copy c, Move m, Drop d, void const *t) noexcept
void(*)(Storage *dst, Storage *src) Move
constexpr AnyActions() noexcept
void(*)(Storage *dst, Storage const *src) Copy
static ANY_ALWAYS_INLINE X & make(Storage *s, std::in_place_type_t< X > vtype, Args &&... args)
static constexpr AnyActions actions
Storage(Storage const &)=delete
Storage & operator=(Storage const &)=delete
Storage(Storage &&)=delete
Storage & operator=(Storage &&)=delete