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