#ifndef CCObject_H #define CCObject_H #pragma once #pragma GCC system_header #include #include #include #include #include using namespace std; class bad_CCObject_cast : public bad_cast { public: virtual const char* what() const noexcept { return "bad CCObject_cast"; } }; [[gnu::noreturn]] inline void __throw_bad_CCObject_cast() { #if __cpp_exceptions throw bad_CCObject_cast{}; #else __builtin_abort(); #endif } #define __cpp_lib_CCObject 201606L class CCObject { // Holds either pointer to a heap object or the contained object itself. union _Storage { constexpr _Storage() : _M_ptr{nullptr} {} // Prevent trivial copies of this type, buffer might hold a non-POD. _Storage(const _Storage&) = delete; _Storage& operator=(const _Storage&) = delete; void* _M_ptr; aligned_storage::type _M_buffer; }; template, bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) && (alignof(_Tp) <= alignof(_Storage))> using _Internal = std::integral_constant; template struct _Manager_internal; // uses small-object optimization template struct _Manager_external; // creates contained object on the heap template using _Manager = __conditional_t<_Internal<_Tp>::value, _Manager_internal<_Tp>, _Manager_external<_Tp>>; template> using _Decay_if_not_CCObject = enable_if_t, _VTp>; /// Emplace with an object created from @p __args as the contained object. template > void __do_emplace(_Args&&... __args) { reset(); _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); _M_manager = &_Mgr::_S_manage; } template > void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) { reset(); _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); _M_manager = &_Mgr::_S_manage; } template using __CCObject_constructible = enable_if<__and_, is_constructible<_Tp, _Args...>>::value, _Res>; template using __CCObject_constructible_t = typename __CCObject_constructible::type; template using __emplace_t = typename __CCObject_constructible<_VTp&, _VTp, _Args...>::type; public: constexpr CCObject() noexcept : _M_manager(nullptr) { } CCObject(const CCObject& __other) { if (!__other.has_value()) _M_manager = nullptr; else { _Arg __arg; __arg._M_CCObject = this; __other._M_manager(_Op_clone, &__other, &__arg); } } CCObject(CCObject&& __other) noexcept { if (!__other.has_value()) _M_manager = nullptr; else { _Arg __arg; __arg._M_CCObject = this; __other._M_manager(_Op_xfer, &__other, &__arg); } } template , typename _Mgr = _Manager<_VTp>, enable_if_t && !__is_in_place_type_v<_VTp>, bool> = true> CCObject(_Tp&& __value) : _M_manager(&_Mgr::_S_manage) { _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value)); } template , typename _Mgr = _Manager<_VTp>, __CCObject_constructible_t<_VTp, _Args&&...> = false> explicit CCObject(in_place_type_t<_Tp>, _Args&&... __args) : _M_manager(&_Mgr::_S_manage) { _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); } template , typename _Mgr = _Manager<_VTp>, __CCObject_constructible_t<_VTp, initializer_list<_Up>&, _Args&&...> = false> explicit CCObject(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) : _M_manager(&_Mgr::_S_manage) { _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); } ~CCObject() { reset(); } CCObject& operator=(const CCObject& __rhs) { *this = CCObject(__rhs); return *this; } CCObject& operator=(CCObject&& __rhs) noexcept { if (!__rhs.has_value()) reset(); else if (this != &__rhs) { reset(); _Arg __arg; __arg._M_CCObject = this; __rhs._M_manager(_Op_xfer, &__rhs, &__arg); } return *this; } template enable_if_t>::value, CCObject&> operator=(_Tp&& __rhs) { *this = CCObject(std::forward<_Tp>(__rhs)); return *this; } template __emplace_t, _Args...> emplace(_Args&&... __args) { using _VTp = decay_t<_Tp>; __do_emplace<_VTp>(std::forward<_Args>(__args)...); return *CCObject::_Manager<_VTp>::_S_access(_M_storage); } template __emplace_t, initializer_list<_Up>&, _Args&&...> emplace(initializer_list<_Up> __il, _Args&&... __args) { using _VTp = decay_t<_Tp>; __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...); return *CCObject::_Manager<_VTp>::_S_access(_M_storage); } void reset() noexcept { if (has_value()) { _M_manager(_Op_destroy, this, nullptr); _M_manager = nullptr; } } void swap(CCObject& __rhs) noexcept { if (!has_value() && !__rhs.has_value()) return; if (has_value() && __rhs.has_value()) { if (this == &__rhs) return; CCObject __tmp; _Arg __arg; __arg._M_CCObject = &__tmp; __rhs._M_manager(_Op_xfer, &__rhs, &__arg); __arg._M_CCObject = &__rhs; _M_manager(_Op_xfer, this, &__arg); __arg._M_CCObject = this; __tmp._M_manager(_Op_xfer, &__tmp, &__arg); } else { CCObject* __empty = !has_value() ? this : &__rhs; CCObject* __full = !has_value() ? &__rhs : this; _Arg __arg; __arg._M_CCObject = __empty; __full->_M_manager(_Op_xfer, __full, &__arg); } } bool has_value() const noexcept { return _M_manager != nullptr; } CCObject Get(){return *this;} void * GetPointer() const; const char* ToString() const; operator int () const; operator double () const; operator float () const; operator const char* () const; #if __cpp_rtti const type_info& type() const noexcept { if (!has_value()) return typeid(void); _Arg __arg; _M_manager(_Op_get_type_info, this, &__arg); return *__arg._M_typeinfo; } #endif template static constexpr bool __is_valid_cast() { return __or_, is_copy_constructible<_Tp>>::value; } private: enum _Op { _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer }; union _Arg { void* _M_obj; const std::type_info* _M_typeinfo; CCObject* _M_CCObject; }; void (*_M_manager)(_Op, const CCObject*, _Arg*); _Storage _M_storage; template friend void* __CCObject_caster(const CCObject* __CCObject); template struct _Manager_internal { static void _S_manage(_Op __which, const CCObject* __CCObjectp, _Arg* __arg); template static void _S_create(_Storage& __storage, _Up&& __value) { void* __addr = &__storage._M_buffer; ::new (__addr) _Tp(std::forward<_Up>(__value)); } template static void _S_create(_Storage& __storage, _Args&&... __args) { void* __addr = &__storage._M_buffer; ::new (__addr) _Tp(std::forward<_Args>(__args)...); } static _Tp* _S_access(const _Storage& __storage) { // The contained object is in __storage._M_buffer const void* __addr = &__storage._M_buffer; return static_cast<_Tp*>(const_cast(__addr)); } }; template struct _Manager_external { static void _S_manage(_Op __which, const CCObject* __CCObjectp, _Arg* __arg); template static void _S_create(_Storage& __storage, _Up&& __value) { __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); } template static void _S_create(_Storage& __storage, _Args&&... __args) { __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...); } static _Tp* _S_access(const _Storage& __storage) { // The contained object is in *__storage._M_ptr return static_cast<_Tp*>(__storage._M_ptr); } }; }; inline void swap(CCObject& __x, CCObject& __y) noexcept { __x.swap(__y); } template inline enable_if_t, _Args...>, CCObject> make_CCObject(_Args&&... __args) { return CCObject(in_place_type<_Tp>, std::forward<_Args>(__args)...); } template inline enable_if_t, initializer_list<_Up>&, _Args...>, CCObject> make_CCObject(initializer_list<_Up> __il, _Args&&... __args) { return CCObject(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); } template inline _ValueType CCObject_cast(const CCObject& __CCObject) { using _Up = __remove_cvref_t<_ValueType>; static_assert(CCObject::__is_valid_cast<_ValueType>(), "模板参数必须是引用或 CopyConstructible 类型"); static_assert(is_constructible_v<_ValueType, const _Up&>, "模板参数必须可以从 const 值构造。"); auto __p = CCObject_cast<_Up>(&__CCObject); if (__p) return static_cast<_ValueType>(*__p); __throw_bad_CCObject_cast(); } template inline _ValueType CCObject_cast(CCObject& __CCObject) { using _Up = __remove_cvref_t<_ValueType>; static_assert(CCObject::__is_valid_cast<_ValueType>(), "模板参数必须是引用或 CopyConstructible 类型"); static_assert(is_constructible_v<_ValueType, _Up&>, "模板参数必须可以从左值构造。"); auto __p = CCObject_cast<_Up>(&__CCObject); if (__p) return static_cast<_ValueType>(*__p); __throw_bad_CCObject_cast(); } template inline _ValueType CCObject_cast(CCObject&& __CCObject) { using _Up = __remove_cvref_t<_ValueType>; static_assert(CCObject::__is_valid_cast<_ValueType>(), "模板参数必须是引用或 CopyConstructible 类型"); static_assert(is_constructible_v<_ValueType, _Up>, "模板参数必须可以从右值构造。"); auto __p = CCObject_cast<_Up>(&__CCObject); if (__p) return static_cast<_ValueType>(std::move(*__p)); __throw_bad_CCObject_cast(); } template void* __CCObject_caster(const CCObject* __CCObject) { using _Up = remove_cv_t<_Tp>; if constexpr (!is_same_v, _Up>) return nullptr; else if constexpr (!is_copy_constructible_v<_Up>) return nullptr; else if (__CCObject->_M_manager == &CCObject::_Manager<_Up>::_S_manage #if __cpp_rtti || __CCObject->type() == typeid(_Tp) #endif ) { return CCObject::_Manager<_Up>::_S_access(__CCObject->_M_storage); } return nullptr; } template inline const _ValueType* CCObject_cast(const CCObject* __CCObject) noexcept { if constexpr (is_object_v<_ValueType>) if (__CCObject) return static_cast<_ValueType*>(__CCObject_caster<_ValueType>(__CCObject)); return nullptr; } template inline _ValueType* CCObject_cast(CCObject* __CCObject) noexcept { if constexpr (is_object_v<_ValueType>) if (__CCObject) return static_cast<_ValueType*>(__CCObject_caster<_ValueType>(__CCObject)); return nullptr; } template void CCObject::_Manager_internal<_Tp>:: _S_manage(_Op __which, const CCObject* __CCObject, _Arg* __arg) { auto __ptr = reinterpret_cast(&__CCObject->_M_storage._M_buffer); switch (__which) { case _Op_access: __arg->_M_obj = const_cast<_Tp*>(__ptr); break; case _Op_get_type_info: #if __cpp_rtti __arg->_M_typeinfo = &typeid(_Tp); #endif break; case _Op_clone: ::new(&__arg->_M_CCObject->_M_storage._M_buffer) _Tp(*__ptr); __arg->_M_CCObject->_M_manager = __CCObject->_M_manager; break; case _Op_destroy: __ptr->~_Tp(); break; case _Op_xfer: ::new(&__arg->_M_CCObject->_M_storage._M_buffer) _Tp (std::move(*const_cast<_Tp*>(__ptr))); __ptr->~_Tp(); __arg->_M_CCObject->_M_manager = __CCObject->_M_manager; const_cast(__CCObject)->_M_manager = nullptr; break; } } template void CCObject::_Manager_external<_Tp>:: _S_manage(_Op __which, const CCObject* __CCObject, _Arg* __arg) { auto __ptr = static_cast(__CCObject->_M_storage._M_ptr); switch (__which) { case _Op_access: __arg->_M_obj = const_cast<_Tp*>(__ptr); break; case _Op_get_type_info: #if __cpp_rtti __arg->_M_typeinfo = &typeid(_Tp); #endif break; case _Op_clone: __arg->_M_CCObject->_M_storage._M_ptr = new _Tp(*__ptr); __arg->_M_CCObject->_M_manager = __CCObject->_M_manager; break; case _Op_destroy: delete __ptr; break; case _Op_xfer: __arg->_M_CCObject->_M_storage._M_ptr = __CCObject->_M_storage._M_ptr; __arg->_M_CCObject->_M_manager = __CCObject->_M_manager; const_cast(__CCObject)->_M_manager = nullptr; break; } } inline CCObject::operator int() const { int i = CCObject_cast(*this); return i; } inline CCObject::operator double() const { auto d = CCObject_cast(*this); return d; } inline CCObject::operator float() const { auto f = CCObject_cast(*this); return f; } inline const char *CCObject::ToString() const { return (const char*)*this; } inline void *CCObject::GetPointer() const { if (auto p = CCObject_cast(*this)) return p; return nullptr; } inline CCObject::operator const char *() const { if (auto s = CCObject_cast(*this)) return s; return nullptr; } #endif