52#ifndef INCLUDE_KI_ANY_H_
53#define INCLUDE_KI_ANY_H_
55#include <initializer_list>
71inline constexpr bool is_in_place_type_v<std::in_place_type_t<T>> =
true;
79 const char*
what() const noexcept
override {
return "bad ki::any_cast"; }
103 template <
typename T,
bool Safe = std::is_nothrow_move_constructible_v<T>,
104 bool Fits = ( sizeof( T ) <= sizeof( Storage ) )
105 && ( alignof( T ) <= alignof( Storage ) )>
106 using Use_Internal_Storage = std::
integral_constant<
bool, Safe && Fits>;
108 template <
typename T>
111 template <
typename T>
114 template <
typename T>
118 template <
typename T,
typename V = std::decay_t<T>>
122 template <
typename T,
typename... Args,
typename Mgr =
Manager<T>>
126 Mgr::do_create(
m_storage, std::forward<Args>( args )... );
131 template <
typename T,
typename U,
typename... Args,
typename Mgr = Manager<T>>
132 void do_emplace( std::initializer_list<U> il, Args&&... args )
135 Mgr::do_create(
m_storage, il, std::forward<Args>( args )... );
139 template <
typename Res,
typename T,
typename... Args>
141 std::enable_if<std::is_copy_constructible_v<T> && std::is_constructible_v<T, Args...>,
144 template <
typename T,
typename... Args>
147 template <
typename V,
typename... Args>
172 if( !other.has_value() )
185 template <
typename T,
typename V = decay_if_not_any<T>,
typename Mgr = Manager<V>,
186 std::enable_if_t<std::is_copy_constructible_v<V> && !is_in_place_type_v<V>,
bool> =
191 Mgr::do_create(
m_storage, std::forward<T>( value ) );
195 template <
typename T,
typename... Args,
typename V = std::decay_t<T>,
typename Mgr = Manager<V>,
197 explicit any( std::in_place_type_t<T>, Args&&... args ) :
m_manager( &Mgr::m_manage_fn )
199 Mgr::do_create(
m_storage, std::forward<Args>( args )... );
203 template <
typename T,
typename U,
typename... Args,
typename V = std::decay_t<T>,
204 typename Mgr = Manager<V>,
205 any_constructible_t<V, std::initializer_list<U>&, Args&&...> =
false>
206 explicit any( std::in_place_type_t<T>, std::initializer_list<U> il, Args&&... args ) :
209 Mgr::do_create(
m_storage, il, std::forward<Args>( args )... );
225 if( !rhs.has_value() )
229 else if(
this != &rhs )
241 template <
typename T>
242 std::enable_if_t<std::is_copy_constructible_v<decay_if_not_any<T>>,
any&>
operator=( T&& rhs )
244 *
this =
any( std::forward<T>( rhs ) );
249 template <
typename T,
typename... Args>
252 using V = std::decay_t<T>;
253 do_emplace<V>( std::forward<Args>( args )... );
258 template <
typename T,
typename U,
typename... Args>
259 any_emplace_t<std::decay_t<T>, std::initializer_list<U>&, Args&&...>
260 emplace( std::initializer_list<U> il, Args&&... args )
262 using V = std::decay_t<T>;
263 do_emplace<V, U>( il, std::forward<Args>( args )... );
312 const std::type_info&
type() const noexcept
315 return typeid( void );
323 template <
typename T>
324 static constexpr bool is_valid_any_cast()
326 return std::is_reference_v<T> || std::is_copy_constructible_v<T>;
351 template <
typename T>
352 friend void* any_caster(
const any*
any );
356 template <
typename T>
361 template <
typename U>
365 ::new( addr ) T( std::forward<U>( value ) );
368 template <
typename... Args>
372 ::new( addr ) T( std::forward<Args>( args )... );
378 const void* addr = &storage.
m_buffer;
379 return static_cast<T*
>(
const_cast<void*
>( addr ) );
384 template <
typename T>
389 template <
typename U>
392 storage.
m_ptr =
new T( std::forward<U>( value ) );
394 template <
typename... Args>
397 storage.
m_ptr =
new T( std::forward<Args>( args )... );
402 return static_cast<T*
>( storage.
m_ptr );
414template <
typename T,
typename... Args>
415std::enable_if_t<std::is_constructible_v<any, std::in_place_type_t<T>, Args...>, any>
418 return any( std::in_place_type<T>, std::forward<Args>( args )... );
422template <
typename T,
typename U,
typename... Args>
424 std::is_constructible_v<any, std::in_place_type_t<T>, std::initializer_list<U>&, Args...>,
426make_any( std::initializer_list<U> il, Args&&... args )
428 return any( std::in_place_type<T>, il, std::forward<Args>( args )... );
441template <
typename ValueType>
444 using U = std::remove_cvref_t<ValueType>;
446 static_assert( any::is_valid_any_cast<ValueType>(),
447 "Template argument must be a reference or CopyConstructible type" );
448 static_assert( std::is_constructible_v<ValueType, const U&>,
449 "Template argument must be constructible from a const value" );
451 auto p = any_cast<U>( &
any );
454 return static_cast<ValueType
>( *p );
470template <
typename ValueType>
473 using U = std::remove_cvref_t<ValueType>;
475 static_assert( any::is_valid_any_cast<ValueType>(),
476 "Template argument must be a reference or CopyConstructible type" );
477 static_assert( std::is_constructible_v<ValueType, U&>,
478 "Template argument must be constructible from an lvalue" );
480 auto p = any_cast<U>( &
any );
483 return static_cast<ValueType
>( *p );
488template <
typename ValueType>
491 using U = std::remove_cvref_t<ValueType>;
493 static_assert( any::is_valid_any_cast<ValueType>(),
494 "Template argument must be a reference or CopyConstructible type" );
495 static_assert( std::is_constructible_v<ValueType, U>,
496 "Template argument must be constructible from an rvalue" );
498 auto p = any_cast<U>( &
any );
501 return static_cast<ValueType
>( std::move( *p ) );
510void* any_caster(
const any* any )
514 using U = std::remove_cv_t<T>;
516 if constexpr( !std::is_same_v<std::decay_t<U>, U> )
522 else if constexpr( !std::is_copy_constructible_v<U> )
527 else if( any->m_manager == &any::Manager<U>::m_manage_fn
528 || any->type().hash_code() ==
typeid( T ).hash_code() )
530 return any::Manager<U>::do_access( any->m_storage );
548template <
typename ValueType>
551 static_assert( !std::is_void_v<ValueType> );
555 if constexpr( std::is_object_v<ValueType> )
558 return static_cast<ValueType*
>( any_caster<ValueType>(
any ) );
564template <
typename ValueType>
567 static_assert( !std::is_void_v<ValueType> );
569 if constexpr( std::is_object_v<ValueType> )
571 return static_cast<ValueType*
>( any_caster<ValueType>(
any ) );
583 case Op_Access: arg->
m_obj =
const_cast<T*
>( ptr );
break;
584 case Op_Get_Type_Info: arg->
m_typeinfo = &
typeid( T );
break;
589 case Op_Destroy: ptr->~T();
break;
594 const_cast<ki::any*
>(
any )->m_manager =
nullptr;
606 case Op_Access: arg->
m_obj =
const_cast<T*
>( ptr );
break;
607 case Op_Get_Type_Info: arg->
m_typeinfo = &
typeid( T );
break;
612 case Op_Destroy:
delete ptr;
break;
616 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
Reports 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)
An implementation of std::any_cast, which uses type_info::hash_code to check validity of cast types.
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)]