56#ifndef INCLUDE_KI_ANY_H_
57#define INCLUDE_KI_ANY_H_
59#include <initializer_list>
75inline constexpr bool is_in_place_type_v<std::in_place_type_t<T>> =
true;
83 const char*
what() const noexcept
override {
return "bad ki::any_cast"; }
107 template <
typename T,
bool Safe = std::is_nothrow_move_constructible_v<T>,
108 bool Fits = ( sizeof( T ) <= sizeof( Storage ) )
109 && ( alignof( T ) <= alignof( Storage ) )>
110 using Use_Internal_Storage = std::
integral_constant<
bool, Safe && Fits>;
112 template <
typename T>
115 template <
typename T>
118 template <
typename T>
122 template <
typename T,
typename V = std::decay_t<T>>
126 template <
typename T,
typename... Args,
typename Mgr =
Manager<T>>
130 Mgr::do_create(
m_storage, std::forward<Args>( args )... );
135 template <
typename T,
typename U,
typename... Args,
typename Mgr = Manager<T>>
136 void do_emplace( std::initializer_list<U> il, Args&&... args )
139 Mgr::do_create(
m_storage, il, std::forward<Args>( args )... );
143 template <
typename Res,
typename T,
typename... Args>
145 std::enable_if<std::is_copy_constructible_v<T> && std::is_constructible_v<T, Args...>,
148 template <
typename T,
typename... Args>
151 template <
typename V,
typename... Args>
176 if( !other.has_value() )
189 template <
typename T,
typename V = decay_if_not_any<T>,
typename Mgr = Manager<V>,
190 std::enable_if_t<std::is_copy_constructible_v<V> && !is_in_place_type_v<V>,
bool> =
195 Mgr::do_create(
m_storage, std::forward<T>( value ) );
199 template <
typename T,
typename... Args,
typename V = std::decay_t<T>,
typename Mgr = Manager<V>,
201 explicit any( std::in_place_type_t<T>, Args&&... args ) :
m_manager( &Mgr::m_manage_fn )
203 Mgr::do_create(
m_storage, std::forward<Args>( args )... );
207 template <
typename T,
typename U,
typename... Args,
typename V = std::decay_t<T>,
208 typename Mgr = Manager<V>,
209 any_constructible_t<V, std::initializer_list<U>&, Args&&...> =
false>
210 explicit any( std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args ) :
213 Mgr::do_create(
m_storage, il, std::forward<Args>( args )... );
229 if( !rhs.has_value() )
233 else if(
this != &rhs )
245 template <
typename T>
246 std::enable_if_t<std::is_copy_constructible_v<decay_if_not_any<T>>,
any&>
operator=( T&& rhs )
248 *
this =
any( std::forward<T>( rhs ) );
253 template <
typename T,
typename... Args>
256 using V = std::decay_t<T>;
257 do_emplace<V>( std::forward<Args>( args )... );
262 template <
typename T,
typename U,
typename... Args>
263 any_emplace_t<std::decay_t<T>, std::initializer_list<U>&, Args&&...>
264 emplace( std::initializer_list<U> il, Args&&... args )
266 using V = std::decay_t<T>;
267 do_emplace<V, U>( il, std::forward<Args>( args )... );
316 const std::type_info&
type() const noexcept
319 return typeid( void );
327 template <
typename T>
328 static constexpr bool is_valid_any_cast()
330 return std::is_reference_v<T> || std::is_copy_constructible_v<T>;
355 template <
typename T>
356 friend void* any_caster(
const any*
any );
360 template <
typename T>
365 template <
typename U>
369 ::new( addr ) T( std::forward<U>( value ) );
372 template <
typename... Args>
376 ::new( addr ) T( std::forward<Args>( args )... );
382 const void* addr = &storage.
m_buffer;
383 return static_cast<T*
>(
const_cast<void*
>( addr ) );
388 template <
typename T>
393 template <
typename U>
396 storage.
m_ptr =
new T( std::forward<U>( value ) );
398 template <
typename... Args>
401 storage.
m_ptr =
new T( std::forward<Args>( args )... );
406 return static_cast<T*
>( storage.
m_ptr );
418template <
typename T,
typename... Args>
419std::enable_if_t<std::is_constructible_v<any, std::in_place_type_t<T>, Args...>, any>
422 return any( std::in_place_type<T>, std::forward<Args>( args )... );
426template <
typename T,
typename U,
typename... Args>
428 std::is_constructible_v<any, std::in_place_type_t<T>, std::initializer_list<U>&, Args...>,
430make_any( std::initializer_list<U> il, Args&&... args )
432 return any( std::in_place_type<T>, il, std::forward<Args>( args )... );
445template <
typename ValueType>
448 using U = std::remove_cvref_t<ValueType>;
450 static_assert( any::is_valid_any_cast<ValueType>(),
451 "Template argument must be a reference or CopyConstructible type" );
452 static_assert( std::is_constructible_v<ValueType, const U&>,
453 "Template argument must be constructible from a const value" );
455 auto p = any_cast<U>( &
any );
458 return static_cast<ValueType
>( *p );
474template <
typename ValueType>
477 using U = std::remove_cvref_t<ValueType>;
479 static_assert( any::is_valid_any_cast<ValueType>(),
480 "Template argument must be a reference or CopyConstructible type" );
481 static_assert( std::is_constructible_v<ValueType, U&>,
482 "Template argument must be constructible from an lvalue" );
484 auto p = any_cast<U>( &
any );
487 return static_cast<ValueType
>( *p );
492template <
typename ValueType>
495 using U = std::remove_cvref_t<ValueType>;
497 static_assert( any::is_valid_any_cast<ValueType>(),
498 "Template argument must be a reference or CopyConstructible type" );
499 static_assert( std::is_constructible_v<ValueType, U>,
500 "Template argument must be constructible from an rvalue" );
502 auto p = any_cast<U>( &
any );
505 return static_cast<ValueType
>( std::move( *p ) );
514void* any_caster(
const any* any )
518 using U = std::remove_cv_t<T>;
520 if constexpr( !std::is_same_v<std::decay_t<U>, U> )
526 else if constexpr( !std::is_copy_constructible_v<U> )
531 else if( any->m_manager == &any::Manager<U>::m_manage_fn
532 || any->type().hash_code() ==
typeid( T ).hash_code() )
534 return any::Manager<U>::do_access( any->m_storage );
552template <
typename ValueType>
555 static_assert( !std::is_void_v<ValueType> );
559 if constexpr( std::is_object_v<ValueType> )
562 return static_cast<ValueType*
>( any_caster<ValueType>(
any ) );
568template <
typename ValueType>
571 static_assert( !std::is_void_v<ValueType> );
573 if constexpr( std::is_object_v<ValueType> )
575 return static_cast<ValueType*
>( any_caster<ValueType>(
any ) );
587 case Op_Access: arg->
m_obj =
const_cast<T*
>( ptr );
break;
588 case Op_Get_Type_Info: arg->
m_typeinfo = &
typeid( T );
break;
593 case Op_Destroy: ptr->~T();
break;
598 const_cast<ki::any*
>(
any )->m_manager =
nullptr;
610 case Op_Access: arg->
m_obj =
const_cast<T*
>( ptr );
break;
611 case Op_Get_Type_Info: arg->
m_typeinfo = &
typeid( T );
break;
616 case Op_Destroy:
delete ptr;
break;
620 const_cast<ki::any*
>(
any )->m_manager =
nullptr;
A type-safe container of any type.
std::enable_if< std::is_copy_constructible_v< T > &&std::is_constructible_v< T, Args... >, Res > any_constructible
typename any_constructible< bool, T, Args... >::type any_constructible_t
any(const any &other)
Copy constructor, copies the state of other.
bool has_value() const noexcept
Report whether there is a contained object or not.
any(std::in_place_type_t< T >, std::initializer_list< U > il, Args &&... args)
Construct with an object created from il and args as the contained object.
constexpr any() noexcept
Default constructor, creates an empty object.
void do_emplace(Args &&... args)
Emplace with an object created from args as the contained object.
void reset() noexcept
If not empty, destroys the contained object.
any(T &&value)
Construct with a copy of value as the contained object.
void swap(any &rhs) noexcept
Exchange state with another object.
typename any_constructible< V &, V, Args... >::type any_emplace_t
any_emplace_t< std::decay_t< T >, std::initializer_list< U > &, Args &&... > emplace(std::initializer_list< U > il, Args &&... args)
Emplace with an object created from il and args as the contained object.
any_emplace_t< std::decay_t< T >, Args... > emplace(Args &&... args)
Emplace with an object created from args as the contained object.
std::conditional_t< Use_Internal_Storage< T >::value, Manager_Internal< T >, Manager_External< T > > Manager
any & operator=(const any &rhs)
Copy the state of another object.
~any()
Destructor, calls reset().
any(any &&other) noexcept
Move constructor, transfer the state from other.
std::enable_if_t<!std::is_same_v< V, any >, V > decay_if_not_any
std::enable_if_t< std::is_copy_constructible_v< decay_if_not_any< T > >, any & > operator=(T &&rhs)
Store a copy of rhs as the contained object.
any & operator=(any &&rhs) noexcept
Move assignment operator.
void do_emplace(std::initializer_list< U > il, Args &&... args)
Emplace with an object created from il and args as the contained object.
any(std::in_place_type_t< T >, Args &&... args)
Construct with an object created from args as the contained object.
void(* m_manager)(Op, const any *, Arg *)
const std::type_info & type() const noexcept
The typeid of the contained object, or typeid(void) if empty.
Exception class thrown by a failed any_cast.
const char * what() const noexcept override
static bool empty(const wxTextEntryBase *aCtrl)
constexpr bool is_in_place_type_v
std::enable_if_t< std::is_constructible_v< any, std::in_place_type_t< T >, Args... >, any > make_any(Args &&... args)
Create a any holding a T constructed from args....
ValueType any_cast(const any &any)
Access the contained object.
static void do_create(Storage &storage, U &&value)
static void m_manage_fn(Op which, const any *any, Arg *arg)
static T * do_access(const Storage &storage)
static void do_create(Storage &storage, Args &&... args)
static void do_create(Storage &storage, Args &&... args)
static T * do_access(const Storage &storage)
static void m_manage_fn(Op which, const any *any, Arg *arg)
static void do_create(Storage &storage, U &&value)
const std::type_info * m_typeinfo
Storage & operator=(const Storage &)=delete
Storage(const Storage &)=delete
unsigned char m_buffer[sizeof(m_ptr)]