#if wxUSE_ANY
+#include <new> // for placement new
#include "wx/string.h"
-#include "wx/meta/movable.h"
#include "wx/meta/if.h"
#include "wx/typeinfo.h"
/**
Default constructor.
*/
- wxAnyValueType();
+ wxAnyValueType()
+ {
+ }
/**
Destructor.
*/
// 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;
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) \
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; \
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__
{
template<typename T>
-class wxAnyValueTypeOpsMovable
+class wxAnyValueTypeOpsInplace
{
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)
{
- 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)
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;
};
template<typename T>
-wxAnyValueTypeImpl<T>* wxAnyValueTypeImpl<T>::sm_instance =
- new wxAnyValueTypeImpl<T>();
+wxAnyValueTypeScopedPtr wxAnyValueTypeImpl<T>::sm_instance = new wxAnyValueTypeImpl<T>();
//
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)
{
- 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)
{
- 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);
}
*/
// 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>();
}
@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
{
}
/**
- 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
{
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;
}
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) )
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);
}
}
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);
}
//
// 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<T*>(NULL))
+ (any).As(static_cast<T*>(NULL))
template<typename T>
-inline bool wxAnyValueType::CheckType(T* reserved)
+inline bool wxAnyValueType::CheckType(T* reserved) const
{
wxUnusedVar(reserved);
return wxAnyValueTypeImpl<T>::IsSameClass(this);