26 #include "type_traits.h"
33 using data_type = add_pointer_t<void>;
36 using is_small = ::std::integral_constant<
38 sizeof(decay_t<Type>) <=
sizeof(
void*)
42 using destroy_function = void (*)(data_type&);
43 using clone_function = void(*)(data_type
const&, data_type&);
44 using type_function = ::std::type_info
const& (*)();
46 destroy_function
const destroy;
47 clone_function
const clone;
48 type_function
const type;
51 template <class Type, bool=is_small<Type>::value>
56 using allocator_type = ::std::allocator<Type>;
57 using allocator_traits = ::std::allocator_traits<allocator_type>;
59 static void clone (data_type
const& source, data_type& data) {
60 allocator_type alloc { };
61 auto const& value =
reinterpret_cast<Type const&
>(source);
62 auto& ref =
reinterpret_cast<Type&
>(data);
63 allocator_traits::construct(alloc, ::std::addressof(ref), value);
66 static void destroy (data_type& data) {
67 allocator_type alloc { };
68 auto& ref =
reinterpret_cast<Type&
>(data);
69 allocator_traits::destroy(alloc, ::std::addressof(ref));
75 using allocator_type = ::std::allocator<Type>;
76 using allocator_traits = ::std::allocator_traits<allocator_type>;
78 static void clone (data_type
const& source, data_type& data) {
79 allocator_type alloc { };
80 auto const& value = *
static_cast<Type* const
>(source);
81 auto pointer = allocator_traits::allocate(alloc, 1);
82 auto scope = make_scope_guard([&alloc, pointer] {
83 allocator_traits::deallocate(alloc, pointer, 1);
85 allocator_traits::construct(alloc, pointer, value);
90 static void destroy (data_type& data) {
91 allocator_type alloc { };
92 auto value =
static_cast<Type*
>(data);
93 allocator_traits::destroy(alloc, value);
94 allocator_traits::deallocate(alloc, value, 1);
103 [] () -> ::std::type_info
const& {
return typeid(Type); }
105 return ::std::addressof(instance);
109 inline any_dispatch
const* get_any_dispatch<void> () {
110 static any_dispatch
const instance = {
112 [] (data_type
const&, data_type&) { },
113 [] () -> ::std::type_info
const& {
return typeid(void); }
115 return ::std::addressof(instance);
122 virtual char const* what ()
const noexcept
override {
123 return "bad any cast";
128 template <
class ValueType>
129 friend ValueType
const* any_cast (
any const*) noexcept;
130 template <
class ValueType>
friend ValueType* any_cast (
any*) noexcept;
133 impl::data_type data;
135 template <
class ValueType>
136 any (ValueType&& value, ::std::true_type&&) :
137 table { impl::get_any_dispatch<decay_t<ValueType>>() },
140 using value_type = decay_t<ValueType>;
141 using allocator_type = ::std::allocator<value_type>;
142 allocator_type alloc { };
143 auto pointer =
reinterpret_cast<value_type*
>(::std::addressof(this->data));
144 ::std::allocator_traits<allocator_type>::construct(
145 alloc, pointer, ::std::forward<ValueType>(value)
149 template <
class ValueType>
150 any (ValueType&& value, ::std::false_type&&) :
151 table { impl::get_any_dispatch<decay_t<ValueType>>() },
154 using value_type = decay_t<ValueType>;
155 using allocator_type = ::std::allocator<value_type>;
156 allocator_type alloc { };
157 auto pointer = ::std::allocator_traits<allocator_type>::allocate(alloc, 1);
158 ::std::allocator_traits<allocator_type>::construct(
159 alloc, pointer, ::std::forward<ValueType>(value)
161 this->data = pointer;
164 template <
class ValueType>
165 ValueType
const* cast (::std::true_type&&)
const {
166 return reinterpret_cast<ValueType const*
>(::std::addressof(this->data));
169 template <
class ValueType>
170 ValueType* cast (::std::true_type&&) {
171 return reinterpret_cast<ValueType*
>(::std::addressof(this->data));
174 template <
class ValueType>
175 ValueType
const* cast (::std::false_type&&)
const {
176 return static_cast<ValueType const*
>(this->data);
179 template <
class ValueType>
180 ValueType* cast (::std::false_type&&) {
181 return static_cast<ValueType*
>(this->data);
186 table { that.table },
188 { this->table->clone(that.data, this->data); }
190 any (
any&& that) noexcept :
191 table { that.table },
194 that.table = impl::get_any_dispatch<void>();
199 table { impl::get_any_dispatch<void>() },
205 class=enable_if_t<! ::std::is_same<any, decay_t<ValueType>>::value>
206 >
any (ValueType&& value) :
207 any { ::std::forward<ValueType>(value), impl::is_small<ValueType> { } }
210 ~
any () noexcept { this->clear(); }
212 any& operator = (
any const& that) {
213 any { that }.swap(*
this);
217 any& operator = (
any&& that) noexcept {
218 any { ::std::move(that) }.swap(*
this);
224 class=enable_if_t<! ::std::is_same<any, decay_t<ValueType>>::value>
225 >
any& operator = (ValueType&& value) {
227 ::std::forward<ValueType>(value),
228 impl::is_small<ValueType> { }
233 void swap (
any& that) noexcept {
235 swap(this->table, that.table);
236 swap(this->data, that.data);
239 void clear () noexcept {
240 this->table->destroy(this->data);
241 this->table = impl::get_any_dispatch<void>();
244 ::std::type_info
const& type ()
const noexcept {
245 return this->table->type();
248 bool empty ()
const noexcept {
249 return this->table == impl::get_any_dispatch<void>();
254 template <
class ValueType>
255 ValueType
const* any_cast (
any const* operand) noexcept {
256 return operand && operand->type() ==
typeid(ValueType)
257 ? operand->cast<ValueType>(impl::is_small<ValueType> { })
261 template <
class ValueType>
262 ValueType* any_cast (any* operand) noexcept {
263 return operand && operand->type() ==
typeid(ValueType)
264 ? operand->cast<ValueType>(impl::is_small<ValueType> { })
271 ::std::is_reference<ValueType>::value or
272 ::std::is_copy_constructible<ValueType>::value
274 > ValueType any_cast (any
const& operand) {
275 using type = remove_reference_t<ValueType>;
276 auto pointer = any_cast<add_const_t<type>>(::std::addressof(operand));
277 if (!pointer) {
throw bad_any_cast { }; }
284 ::std::is_reference<ValueType>::value or
285 ::std::is_copy_constructible<ValueType>::value
287 > ValueType any_cast (any&& operand) {
288 using type = remove_reference_t<ValueType>;
289 auto pointer = any_cast<type>(::std::addressof(operand));
290 if (!pointer) {
throw bad_any_cast { }; }
297 ::std::is_reference<ValueType>::value or
298 ::std::is_copy_constructible<ValueType>::value
300 > ValueType any_cast (any& operand) {
301 using type = remove_reference_t<ValueType>;
302 auto pointer = any_cast<type>(::std::addressof(operand));
303 if (!pointer) {
throw bad_any_cast { }; }
307 inline void swap (any& lhs, any& rhs) noexcept { lhs.swap(rhs); }