]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/any.h
Applied rowspan patch #15276 (dghart)
[wxWidgets.git] / include / wx / any.h
index b5dac8fb7caf8f2391a92a9a4bb7ced19158c2b2..2651ce219ce42684059fc19fd44f910507992bc3 100644 (file)
 
 #if wxUSE_ANY
 
 
 #if wxUSE_ANY
 
+#include <new> // for placement new
 #include "wx/string.h"
 #include "wx/string.h"
-#include "wx/meta/movable.h"
 #include "wx/meta/if.h"
 #include "wx/typeinfo.h"
 #include "wx/meta/if.h"
 #include "wx/typeinfo.h"
-
+#include "wx/list.h"
 
 // Size of the wxAny value buffer.
 enum
 
 // Size of the wxAny value buffer.
 enum
@@ -56,7 +56,9 @@ public:
     /**
         Default constructor.
     */
     /**
         Default constructor.
     */
-    wxAnyValueType();
+    wxAnyValueType()
+    {
+    }
 
     /**
         Destructor.
 
     /**
         Destructor.
@@ -102,7 +104,7 @@ public:
         a specific C++ data type.
 
         @remarks This template function does not work on some older compilers
         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.
 
                 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 <typename T>
     */
     // FIXME-VC6: remove this hack when VC6 is no longer supported
     template <typename T>
-    bool CheckType(T* reserved = NULL);
+    bool CheckType(T* reserved = NULL) const;
+
+#if wxUSE_EXTENDED_RTTI
+    virtual const wxTypeInfo* GetTypeInfo() const = 0;
+#endif
 private:
 };
 
 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) \
 //
 // 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.
     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; \
 */
 #define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
     friend class wxAny; \
@@ -134,23 +165,23 @@ private:
 public: \
     static bool IsSameClass(const wxAnyValueType* otherType) \
     { \
 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: \
     } \
     virtual bool IsSameType(const wxAnyValueType* otherType) const \
     { \
         return IsSameClass(otherType); \
     } \
 private: \
-    static CLS* sm_instance; \
+    static wxAnyValueTypeScopedPtr sm_instance; \
 public: \
     static wxAnyValueType* GetInstance() \
     { \
 public: \
     static wxAnyValueType* GetInstance() \
     { \
-        return sm_instance; \
+        return sm_instance.get(); \
     }
 
 
 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
     }
 
 
 #define WX_IMPLEMENT_ANY_VALUE_TYPE(CLS) \
-    CLS* CLS::sm_instance = new CLS();
+wxAnyValueTypeScopedPtr CLS::sm_instance(new CLS());
 
 
 #ifdef __VISUALC6__
 
 
 #ifdef __VISUALC6__
@@ -166,23 +197,29 @@ namespace wxPrivate
 {
 
 template<typename T>
 {
 
 template<typename T>
-class wxAnyValueTypeOpsMovable
+class wxAnyValueTypeOpsInplace
 {
 public:
     static void DeleteValue(wxAnyValueBuffer& buf)
     {
 {
 public:
     static void DeleteValue(wxAnyValueBuffer& buf)
     {
-        wxUnusedVar(buf);
+        T* value = reinterpret_cast<T*>(&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)
     {
     }
 
     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)
     {
     }
 
     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<const T*>(&buf.m_buffer[0]);
         // GCC's 'type-punned pointer will break strict-aliasing rules'
         // warning.
         const T* value = reinterpret_cast<const T*>(&buf.m_buffer[0]);
@@ -243,9 +280,8 @@ public:
 template<typename T>
 class wxAnyValueTypeImplBase : public wxAnyValueType
 {
 template<typename T>
 class wxAnyValueTypeImplBase : public wxAnyValueType
 {
-    typedef typename wxIf< wxIsMovable<T>::value &&
-                                sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE,
-                           wxPrivate::wxAnyValueTypeOpsMovable<T>,
+    typedef typename wxIf< sizeof(T) <= WX_ANY_VALUE_BUFFER_SIZE,
+                           wxPrivate::wxAnyValueTypeOpsInplace<T>,
                            wxPrivate::wxAnyValueTypeOpsGeneric<T> >::value
             Ops;
 
                            wxPrivate::wxAnyValueTypeOpsGeneric<T> >::value
             Ops;
 
@@ -282,6 +318,12 @@ public:
     {
         return Ops::GetValue(buf);
     }
     {
         return Ops::GetValue(buf);
     }
+#if wxUSE_EXTENDED_RTTI
+    virtual const wxTypeInfo* GetTypeInfo() const 
+    {
+        return wxGetTypeInfo((T*)NULL);
+    }
+#endif
 };
 
 
 };
 
 
@@ -309,15 +351,14 @@ public:
 };
 
 template<typename T>
 };
 
 template<typename T>
-wxAnyValueTypeImpl<T>* wxAnyValueTypeImpl<T>::sm_instance =
-    new wxAnyValueTypeImpl<T>();
+wxAnyValueTypeScopedPtr wxAnyValueTypeImpl<T>::sm_instance = new wxAnyValueTypeImpl<T>();
 
 
 //
 // Helper macro for using same base value type implementation for multiple
 // actual C++ data types.
 //
 
 
 //
 // 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<T> : public wxAnyValueTypeImpl##CLSTYPE \
 { \
 template<> \
 class wxAnyValueTypeImpl<T> : public wxAnyValueTypeImpl##CLSTYPE \
 { \
@@ -338,9 +379,21 @@ public: \
         const UseDataType* sptr = \
             reinterpret_cast<const UseDataType*>(voidPtr); \
         return static_cast<T>(*sptr); \
         const UseDataType* sptr = \
             reinterpret_cast<const UseDataType*>(voidPtr); \
         return static_cast<T>(*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
 
 //
 //  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
 // (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"
 // be needed).
 #if wxUSE_DATETIME
     #include "wx/datetime.h"
@@ -702,19 +755,19 @@ public:
     template<typename T>
     wxAny(const T& value)
     {
     template<typename T>
     wxAny(const T& value)
     {
-        m_type = wxAnyValueTypeImpl<T>::sm_instance;
+        m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
     }
 
     // These two constructors are needed to deal with string literals
     wxAny(const char* value)
     {
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
     }
 
     // These two constructors are needed to deal with string literals
     wxAny(const char* value)
     {
-        m_type = wxAnyValueTypeImpl<const char*>::sm_instance;
+        m_type = wxAnyValueTypeImpl<const char*>::sm_instance.get();
         wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer);
     }
     wxAny(const wchar_t* value)
     {
         wxAnyValueTypeImpl<const char*>::SetValue(value, m_buffer);
     }
     wxAny(const wchar_t* value)
     {
-        m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance;
+        m_type = wxAnyValueTypeImpl<const wchar_t*>::sm_instance.get();
         wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer);
     }
 
         wxAnyValueTypeImpl<const wchar_t*>::SetValue(value, m_buffer);
     }
 
@@ -746,7 +799,7 @@ public:
     */
     // FIXME-VC6: remove this hack when VC6 is no longer supported
     template <typename T>
     */
     // FIXME-VC6: remove this hack when VC6 is no longer supported
     template <typename T>
-    bool CheckType(T* = NULL)
+    bool CheckType(T* = NULL) const
     {
         return m_type->CheckType<T>();
     }
     {
         return m_type->CheckType<T>();
     }
@@ -756,8 +809,9 @@ public:
 
         @remarks You cannot reliably test whether two wxAnys are of
                  same value type by simply comparing return values
 
         @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<T>() template function.
+                 of wxAny::GetType(). Instead, use wxAny::HasSameType().
+
+        @see HasSameType()
     */
     const wxAnyValueType* GetType() const
     {
     */
     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
     {
     */
     bool IsNull() const
     {
@@ -789,7 +852,7 @@ public:
     wxAny& operator=(const T &value)
     {
         m_type->DeleteValue(m_buffer);
     wxAny& operator=(const T &value)
     {
         m_type->DeleteValue(m_buffer);
-        m_type = wxAnyValueTypeImpl<T>::sm_instance;
+        m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
         return *this;
     }
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
         return *this;
     }
@@ -849,6 +912,8 @@ public:
     WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t, wxULongLong_t)
 #endif
 
     WXANY_IMPLEMENT_INT_EQ_OP(wxLongLong_t, wxULongLong_t)
 #endif
 
+    wxGCC_WARNING_SUPPRESS(float-equal)
+
     bool operator==(float value) const
     {
         if ( !wxAnyValueTypeImpl<float>::IsSameClass(m_type) )
     bool operator==(float value) const
     {
         if ( !wxAnyValueTypeImpl<float>::IsSameClass(m_type) )
@@ -869,6 +934,8 @@ public:
                 (wxAnyValueTypeImpl<double>::GetValue(m_buffer));
     }
 
                 (wxAnyValueTypeImpl<double>::GetValue(m_buffer));
     }
 
+    wxGCC_WARNING_RESTORE(float-equal)
+
     bool operator==(bool value) const
     {
         if ( !wxAnyValueTypeImpl<bool>::IsSameClass(m_type) )
     bool operator==(bool value) const
     {
         if ( !wxAnyValueTypeImpl<bool>::IsSameClass(m_type) )
@@ -893,7 +960,7 @@ public:
         no type conversion is performed, so if the type is incorrect an
         assertion failure will occur.
 
         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.
 
                  is useful when a string literal (which are treated as
                  const char* and const wchar_t*) has been assigned to wxAny.
 
@@ -926,11 +993,17 @@ public:
         return value;
     }
 
         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.
 
         variant to the type that T* value is.
 
-        @return Returns @true if conversion was succesfull.
+        @return Returns @true if conversion was successful.
     */
     template<typename T>
     bool GetAs(T* value) const
     */
     template<typename T>
     bool GetAs(T* value) const
@@ -938,7 +1011,7 @@ public:
         if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
         {
             wxAnyValueType* otherType =
         if ( !wxAnyValueTypeImpl<T>::IsSameClass(m_type) )
         {
             wxAnyValueType* otherType =
-                wxAnyValueTypeImpl<T>::sm_instance;
+                wxAnyValueTypeImpl<T>::sm_instance.get();
             wxAnyValueBuffer temp_buf;
 
             if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) )
             wxAnyValueBuffer temp_buf;
 
             if ( !m_type->ConvertValue(m_buffer, otherType, temp_buf) )
@@ -995,7 +1068,7 @@ private:
         else
         {
             // If everything else fails, wrap the whole wxVariantData
         else
         {
             // If everything else fails, wrap the whole wxVariantData
-            m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance;
+            m_type = wxAnyValueTypeImpl<wxVariantData*>::sm_instance.get();
             wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
         }
     }
             wxAnyValueTypeImpl<wxVariantData*>::SetValue(data, m_buffer);
         }
     }
@@ -1005,7 +1078,7 @@ private:
     void Assign(const T &value)
     {
         m_type->DeleteValue(m_buffer);
     void Assign(const T &value)
     {
         m_type->DeleteValue(m_buffer);
-        m_type = wxAnyValueTypeImpl<T>::sm_instance;
+        m_type = wxAnyValueTypeImpl<T>::sm_instance.get();
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
     }
 
         wxAnyValueTypeImpl<T>::SetValue(value, m_buffer);
     }
 
@@ -1028,13 +1101,13 @@ private:
 
 
 template<typename T>
 
 
 template<typename T>
-inline bool wxAnyValueType::CheckType(T* reserved)
+inline bool wxAnyValueType::CheckType(T* reserved) const
 {
     wxUnusedVar(reserved);
     return wxAnyValueTypeImpl<T>::IsSameClass(this);
 }
 
 {
     wxUnusedVar(reserved);
     return wxAnyValueTypeImpl<T>::IsSameClass(this);
 }
 
-
+WX_DECLARE_LIST_WITH_DECL(wxAny, wxAnyList, class WXDLLIMPEXP_BASE);
 
 #endif // wxUSE_ANY
 
 
 #endif // wxUSE_ANY