update kiwano::any
This commit is contained in:
parent
01f44fef80
commit
720d1fd6e0
|
|
@ -21,6 +21,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
namespace kiwano
|
namespace kiwano
|
||||||
{
|
{
|
||||||
|
|
@ -28,6 +29,18 @@ namespace kiwano
|
||||||
inline namespace core
|
inline namespace core
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class bad_any_cast : public std::exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bad_any_cast() {}
|
||||||
|
|
||||||
|
virtual const char* what() const override
|
||||||
|
{
|
||||||
|
return "bad and cast";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class any
|
class any
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -38,11 +51,11 @@ public:
|
||||||
template <
|
template <
|
||||||
typename _Ty,
|
typename _Ty,
|
||||||
typename _Decayed = typename std::decay<_Ty>::type,
|
typename _Decayed = typename std::decay<_Ty>::type,
|
||||||
typename = typename std::enable_if<std::is_copy_constructible<_Decayed>::value>::type
|
typename std::enable_if<std::is_copy_constructible<_Decayed>::value, int>::type = 0
|
||||||
>
|
>
|
||||||
any(_Ty&& val) : storage_{}
|
any(_Ty&& val) : storage_{}
|
||||||
{
|
{
|
||||||
emplace<_Decayed>(std::forward<_Ty&&>(val));
|
emplace<_Decayed>(std::forward<_Ty>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
|
|
@ -57,22 +70,7 @@ public:
|
||||||
|
|
||||||
any(const any& rhs) : storage_{}
|
any(const any& rhs) : storage_{}
|
||||||
{
|
{
|
||||||
if (rhs.has_value())
|
copy_from(rhs);
|
||||||
{
|
|
||||||
typeinfo() = rhs.typeinfo();
|
|
||||||
storage_.is_small_ = rhs.storage_.is_small_;
|
|
||||||
|
|
||||||
if (rhs.has_small_type())
|
|
||||||
{
|
|
||||||
small_rtti() = rhs.small_rtti();
|
|
||||||
small_rtti().copy(small_data(), rhs.small_data());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
big_rtti() = rhs.big_rtti();
|
|
||||||
big_data() = big_rtti().copy(rhs.big_data());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
any(any&& rhs) noexcept : storage_{}
|
any(any&& rhs) noexcept : storage_{}
|
||||||
|
|
@ -100,7 +98,10 @@ public:
|
||||||
return typeinfo() != nullptr;
|
return typeinfo() != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename _Decayed, typename... _Args>
|
template <
|
||||||
|
typename _Decayed,
|
||||||
|
typename... _Args
|
||||||
|
>
|
||||||
void emplace(_Args&&... args)
|
void emplace(_Args&&... args)
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
|
|
@ -119,6 +120,58 @@ public:
|
||||||
tidy();
|
tidy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
_Ty* cast_pointer() noexcept
|
||||||
|
{
|
||||||
|
return const_cast<_Ty*>(const_cast<const any*>(this)->cast_pointer<_Ty>());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
const _Ty* cast_pointer() const noexcept
|
||||||
|
{
|
||||||
|
static_assert(!std::is_void<_Ty>::value, "kiwano::any cannot contain void");
|
||||||
|
|
||||||
|
const type_info* const info = typeinfo();
|
||||||
|
if (info && (*info == typeid(std::decay<_Ty>::type)))
|
||||||
|
{
|
||||||
|
if (has_small_type())
|
||||||
|
{
|
||||||
|
return static_cast<const _Ty*>(small_data());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return static_cast<const _Ty*>(big_data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
_Ty cast()
|
||||||
|
{
|
||||||
|
using _Decayed = typename std::decay<_Ty>::type;
|
||||||
|
|
||||||
|
const auto ptr = cast_pointer<_Decayed>();
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
throw bad_any_cast{};
|
||||||
|
}
|
||||||
|
return static_cast<_Ty>(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
_Ty cast() const
|
||||||
|
{
|
||||||
|
using _Decayed = typename std::decay<_Ty>::type;
|
||||||
|
|
||||||
|
const auto ptr = cast_pointer<_Decayed>();
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
throw bad_any_cast{};
|
||||||
|
}
|
||||||
|
return static_cast<_Ty>(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
any& operator=(const any& rhs)
|
any& operator=(const any& rhs)
|
||||||
{
|
{
|
||||||
*this = any(rhs);
|
*this = any(rhs);
|
||||||
|
|
@ -143,7 +196,10 @@ protected:
|
||||||
return storage_.small_.info_;
|
return storage_.small_.info_;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename _Decayed, typename... _Args>
|
template <
|
||||||
|
typename _Decayed,
|
||||||
|
typename... _Args
|
||||||
|
>
|
||||||
void store(std::true_type, _Args&&... args)
|
void store(std::true_type, _Args&&... args)
|
||||||
{
|
{
|
||||||
storage_.is_small_ = true;
|
storage_.is_small_ = true;
|
||||||
|
|
@ -153,7 +209,10 @@ protected:
|
||||||
::new (small_data()) _Decayed(std::forward<_Args>(args)...);
|
::new (small_data()) _Decayed(std::forward<_Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename _Decayed, typename... _Args>
|
template <
|
||||||
|
typename _Decayed,
|
||||||
|
typename... _Args
|
||||||
|
>
|
||||||
void store(std::false_type, _Args&&... args)
|
void store(std::false_type, _Args&&... args)
|
||||||
{
|
{
|
||||||
storage_.is_small_ = false;
|
storage_.is_small_ = false;
|
||||||
|
|
@ -180,6 +239,26 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void copy_from(const any& rhs)
|
||||||
|
{
|
||||||
|
if (rhs.has_value())
|
||||||
|
{
|
||||||
|
typeinfo() = rhs.typeinfo();
|
||||||
|
storage_.is_small_ = rhs.storage_.is_small_;
|
||||||
|
|
||||||
|
if (rhs.has_small_type())
|
||||||
|
{
|
||||||
|
small_rtti() = rhs.small_rtti();
|
||||||
|
small_rtti().copy(small_data(), rhs.small_data());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
big_rtti() = rhs.big_rtti();
|
||||||
|
big_data() = big_rtti().copy(rhs.big_data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void move_from(any&& rhs) noexcept
|
void move_from(any&& rhs) noexcept
|
||||||
{
|
{
|
||||||
if (rhs.has_value())
|
if (rhs.has_value())
|
||||||
|
|
@ -196,10 +275,10 @@ protected:
|
||||||
{
|
{
|
||||||
big_rtti() = rhs.big_rtti();
|
big_rtti() = rhs.big_rtti();
|
||||||
big_data() = rhs.big_data();
|
big_data() = rhs.big_data();
|
||||||
}
|
|
||||||
rhs.typeinfo() = nullptr;
|
rhs.typeinfo() = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void* small_data()
|
inline void* small_data()
|
||||||
{
|
{
|
||||||
|
|
@ -227,10 +306,10 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static const auto ANY_SPACE_SIZE = 16U;
|
static const auto ANY_SMALL_SPACE_SIZE = 16U;
|
||||||
|
|
||||||
template <typename _Ty>
|
template <typename _Ty>
|
||||||
struct decayed_is_small : public std::bool_constant<sizeof(_Ty) <= ANY_SPACE_SIZE>
|
struct decayed_is_small : public std::bool_constant<sizeof(_Ty) <= ANY_SMALL_SPACE_SIZE>
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -274,7 +353,7 @@ protected:
|
||||||
{
|
{
|
||||||
using destroy_func = void(void*);
|
using destroy_func = void(void*);
|
||||||
using copy_func = void* (void*, const void*);
|
using copy_func = void* (void*, const void*);
|
||||||
using move_func = void*(void*, const void*);
|
using move_func = void*(void*, void*);
|
||||||
|
|
||||||
small_storage_rtti()
|
small_storage_rtti()
|
||||||
{
|
{
|
||||||
|
|
@ -310,9 +389,9 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename _Ty>
|
template <typename _Ty>
|
||||||
static void* move_impl(void* const target, const void* const ptr) noexcept
|
static void* move_impl(void* const target, void* const ptr) noexcept
|
||||||
{
|
{
|
||||||
return ::new (static_cast<_Ty*>(target)) _Ty(std::move(*static_cast<const _Ty*>(ptr)));
|
return ::new (static_cast<_Ty*>(target)) _Ty(std::move(*static_cast<_Ty*>(ptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy_func* destroy;
|
destroy_func* destroy;
|
||||||
|
|
@ -346,7 +425,7 @@ protected:
|
||||||
{
|
{
|
||||||
const type_info* info_;
|
const type_info* info_;
|
||||||
small_storage_rtti rtti_;
|
small_storage_rtti rtti_;
|
||||||
char buffer_[ANY_SPACE_SIZE];
|
char buffer_[ANY_SMALL_SPACE_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct big_storage
|
struct big_storage
|
||||||
|
|
@ -369,6 +448,64 @@ protected:
|
||||||
storage storage_;
|
storage storage_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// any_cast functions
|
||||||
|
//
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
_Ty* any_cast(any* const a) noexcept
|
||||||
|
{
|
||||||
|
return a->cast_pointer<_Ty>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
const _Ty* any_cast(const any* const a) noexcept
|
||||||
|
{
|
||||||
|
return a->cast_pointer<_Ty>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
_Ty any_cast(any& a)
|
||||||
|
{
|
||||||
|
const auto ptr = any_cast<std::decay<_Ty>::type>(&a);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
throw bad_any_cast{};
|
||||||
|
}
|
||||||
|
return static_cast<_Ty>(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
const _Ty any_cast(const any& a)
|
||||||
|
{
|
||||||
|
const auto ptr = any_cast<std::decay<_Ty>::type>(&a);
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
throw bad_any_cast{};
|
||||||
|
}
|
||||||
|
return static_cast<_Ty>(*ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Ty>
|
||||||
|
_Ty any_cast(any&& a)
|
||||||
|
{
|
||||||
|
_Ty* ptr = a.cast_pointer<_Ty>();
|
||||||
|
if (!ptr)
|
||||||
|
{
|
||||||
|
throw bad_any_cast{};
|
||||||
|
}
|
||||||
|
return static_cast<_Ty>(std::move(*ptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace core
|
||||||
|
|
||||||
|
} // namespace kiwano
|
||||||
|
|
||||||
|
namespace std
|
||||||
|
{
|
||||||
|
inline void swap(kiwano::core::any& lhs, kiwano::core::any& rhs) noexcept
|
||||||
|
{
|
||||||
|
lhs.swap(rhs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue