X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/153107b4021fe0e6c3ad2ed510d3225f138eee83..cbef7338c1c7763042704c74d5ee6f62c7e10733:/include/wx/any.h diff --git a/include/wx/any.h b/include/wx/any.h index 64930ef66b..6e38772532 100644 --- a/include/wx/any.h +++ b/include/wx/any.h @@ -16,11 +16,11 @@ #if wxUSE_ANY +#include // for placement new #include "wx/string.h" -#include "wx/meta/movable.h" #include "wx/meta/if.h" #include "wx/typeinfo.h" - +#include "wx/list.h" // Size of the wxAny value buffer. enum @@ -56,7 +56,9 @@ public: /** Default constructor. */ - wxAnyValueType(); + wxAnyValueType() + { + } /** Destructor. @@ -102,7 +104,7 @@ public: a specific C++ data type. @remarks This template function does not work on some older compilers - (such as Visual C++ 6.0). For full compiler ccompatibility + (such as Visual C++ 6.0). For full compiler compatibility please use wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) macro instead. @@ -110,10 +112,34 @@ public: */ // FIXME-VC6: remove this hack when VC6 is no longer supported template - bool CheckType(T* reserved = NULL); + bool CheckType(T* reserved = NULL) const; + +#if wxUSE_EXTENDED_RTTI + virtual const wxTypeInfo* GetTypeInfo() const = 0; +#endif +private: +}; + + +// +// We need to allocate wxAnyValueType instances in heap, and need to use +// scoped ptr to properly deallocate them in dynamic library use cases. +// Here we have a minimal specialized scoped ptr implementation to deal +// with various compiler-specific problems with template class' static +// member variable of template type with explicit constructor which +// is initialized in global scope. +// +class wxAnyValueTypeScopedPtr +{ +public: + wxAnyValueTypeScopedPtr(wxAnyValueType* ptr) : m_ptr(ptr) { } + ~wxAnyValueTypeScopedPtr() { delete m_ptr; } + wxAnyValueType* get() const { return m_ptr; } private: + wxAnyValueType* m_ptr; }; + // // This method of checking the type is compatible with VC6 #define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \ @@ -127,6 +153,11 @@ private: facilitate sub-type system which allows, for instance, wxAny with signed short '15' to be treated equal to wxAny with signed long long '15'. Having sm_instance is important here. + + NB: We really need to have wxAnyValueType instances allocated + in heap. They are stored as static template member variables, + and with them we just can't be too careful (eg. not allocating + them in heap broke the type identification in GCC). */ #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \ friend class wxAny; \ @@ -134,23 +165,23 @@ private: public: \ static bool IsSameClass(const wxAnyValueType* otherType) \ { \ - return wxTypeId(*sm_instance) == wxTypeId(*otherType); \ + return wxTypeId(*sm_instance.get()) == wxTypeId(*otherType); \ } \ virtual bool IsSameType(const wxAnyValueType* otherType) const \ { \ return IsSameClass(otherType); \ } \ private: \ - static CLS* sm_instance; \ + static wxAnyValueTypeScopedPtr sm_instance; \ public: \ static wxAnyValueType* GetInstance() \ { \ - return sm_instance; \ + return sm_instance.get(); \ } #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \ - CLS* CLS::sm_instance = new CLS(); +wxAnyValueTypeScopedPtr CLS::sm_instance(new CLS()); #ifdef __VISUALC6__ @@ -166,23 +197,29 @@ namespace wxPrivate { template -class wxAnyValueTypeOpsMovable +class wxAnyValueTypeOpsInplace { public: static void DeleteValue(wxAnyValueBuffer& buf) { - wxUnusedVar(buf); + T* value = reinterpret_cast(&buf.m_buffer[0]); + value->~T(); + + // Some compiler may given 'unused variable' warnings without this + wxUnusedVar(value); } static void SetValue(const T& value, wxAnyValueBuffer& buf) { - memcpy(buf.m_buffer, &value, sizeof(T)); + // Use placement new + void* const place = buf.m_buffer; + ::new(place) T(value); } static const T& GetValue(const wxAnyValueBuffer& buf) { - // Breaking this code into two lines should supress + // Breaking this code into two lines should suppress // GCC's 'type-punned pointer will break strict-aliasing rules' // warning. const T* value = reinterpret_cast(&buf.m_buffer[0]); @@ -243,9 +280,8 @@ public: template class wxAnyValueTypeImplBase : public wxAnyValueType { - typedef typename wxIf< wxIsMovable::value && - sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE, - wxPrivate::wxAnyValueTypeOpsMovable, + typedef typename wxIf< sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE, + wxPrivate::wxAnyValueTypeOpsInplace, wxPrivate::wxAnyValueTypeOpsGeneric >::value Ops; @@ -282,6 +318,12 @@ public: { return Ops::GetValue(buf); } +#if wxUSE_EXTENDED_RTTI + virtual const wxTypeInfo* GetTypeInfo() const + { + return wxGetTypeInfo((T*)NULL); + } +#endif }; @@ -309,15 +351,14 @@ public: }; template -wxAnyValueTypeImpl* wxAnyValueTypeImpl::sm_instance = - new wxAnyValueTypeImpl(); +wxAnyValueTypeScopedPtr wxAnyValueTypeImpl::sm_instance = new wxAnyValueTypeImpl(); // // Helper macro for using same base value type implementation for multiple // actual C++ data types. // -#define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ +#define _WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ template<> \ class wxAnyValueTypeImpl : public wxAnyValueTypeImpl##CLSTYPE \ { \ @@ -338,9 +379,21 @@ public: \ const UseDataType* sptr = \ reinterpret_cast(voidPtr); \ return static_cast(*sptr); \ + } + +#if wxUSE_EXTENDED_RTTI +#define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ +_WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE)\ + virtual const wxTypeInfo* GetTypeInfo() const \ + { \ + return wxGetTypeInfo((T*)NULL); \ } \ }; - +#else +#define WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE) \ +_WX_ANY_DEFINE_SUB_TYPE(T, CLSTYPE)\ +}; +#endif // // Integer value types @@ -527,7 +580,7 @@ public: \ // (this is needed only for types that are referred to from wxBase. // currently we may not use any of these types from there, but let's // use the macro on at least one to make sure it compiles since we can't -// really test it properly in unittests since a separate DLL would +// really test it properly in unit tests since a separate DLL would // be needed). #if wxUSE_DATETIME #include "wx/datetime.h" @@ -702,19 +755,19 @@ public: template wxAny(const T& value) { - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } // These two constructors are needed to deal with string literals wxAny(const char* value) { - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } wxAny(const wchar_t* value) { - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } @@ -746,7 +799,7 @@ public: */ // FIXME-VC6: remove this hack when VC6 is no longer supported template - bool CheckType(T* = NULL) + bool CheckType(T* = NULL) const { return m_type->CheckType(); } @@ -756,8 +809,9 @@ public: @remarks You cannot reliably test whether two wxAnys are of same value type by simply comparing return values - of wxAny::GetType(). Instead use - wxAnyValueType::CheckType() template function. + of wxAny::GetType(). Instead, use wxAny::HasSameType(). + + @see HasSameType() */ const wxAnyValueType* GetType() const { @@ -765,7 +819,16 @@ public: } /** - Tests if wxAny is null (that is, whether there is data). + Returns @true if this and another wxAny have the same + value type. + */ + bool HasSameType(const wxAny& other) const + { + return GetType()->IsSameType(other.GetType()); + } + + /** + Tests if wxAny is null (that is, whether there is no data). */ bool IsNull() const { @@ -789,7 +852,7 @@ public: wxAny& operator=(const T &value) { m_type->DeleteValue(m_buffer); - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); return *this; } @@ -893,7 +956,7 @@ public: no type conversion is performed, so if the type is incorrect an assertion failure will occur. - @remarks For conveniency, conversion is done when T is wxString. This + @remarks For convenience, conversion is done when T is wxString. This is useful when a string literal (which are treated as const char* and const wchar_t*) has been assigned to wxAny. @@ -926,11 +989,17 @@ public: return value; } +#if wxUSE_EXTENDED_RTTI + const wxTypeInfo* GetTypeInfo() const + { + return m_type->GetTypeInfo(); + } +#endif /** - Template function that etrieves and converts the value of this + Template function that retrieves and converts the value of this variant to the type that T* value is. - @return Returns @true if conversion was succesfull. + @return Returns @true if conversion was successful. */ template bool GetAs(T* value) const @@ -938,7 +1007,7 @@ public: if ( !wxAnyValueTypeImpl::IsSameClass(m_type) ) { wxAnyValueType* otherType = - wxAnyValueTypeImpl::sm_instance; + wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueBuffer temp_buf; if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) ) @@ -995,7 +1064,7 @@ private: else { // If everything else fails, wrap the whole wxVariantData - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(data, m_buffer); } } @@ -1005,7 +1074,7 @@ private: void Assign(const T &value) { m_type->DeleteValue(m_buffer); - m_type = wxAnyValueTypeImpl::sm_instance; + m_type = wxAnyValueTypeImpl::sm_instance.get(); wxAnyValueTypeImpl::SetValue(value, m_buffer); } @@ -1018,23 +1087,23 @@ private: // // This method of checking the type is compatible with VC6 #define wxANY_CHECK_TYPE(any, T) \ - wxANY_VALUE_TYPE_CHECK_TYPE(any.GetType(), T) + wxANY_VALUE_TYPE_CHECK_TYPE((any).GetType(), T) // // This method of getting the value is compatible with VC6 #define wxANY_AS(any, T) \ - any.As(static_cast(NULL)) + (any).As(static_cast(NULL)) template -inline bool wxAnyValueType::CheckType(T* reserved) +inline bool wxAnyValueType::CheckType(T* reserved) const { wxUnusedVar(reserved); return wxAnyValueTypeImpl::IsSameClass(this); } - +WX_DECLARE_LIST_WITH_DECL(wxAny, wxAnyList, class WXDLLIMPEXP_BASE); #endif // wxUSE_ANY