Added typeinfo.h which implements wxTypeId, using C++ RTTI if available. wxAny and Unbind<>() code are updated to use it. Added and updated related unit tests.
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62690 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
#include "wx/string.h"
|
||||
#include "wx/meta/movable.h"
|
||||
#include "wx/meta/if.h"
|
||||
#include "wx/typeinfo.h"
|
||||
|
||||
|
||||
// Size of the wxAny value buffer.
|
||||
@@ -43,9 +44,6 @@ union wxAnyValueBuffer
|
||||
wxByte m_buffer[WX_ANY_VALUE_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
typedef void (*wxAnyClassInfo)();
|
||||
|
||||
|
||||
//
|
||||
// wxAnyValueType is base class for value type functionality for C++ data
|
||||
// types used with wxAny. Usually the default template (wxAnyValueTypeImpl<>)
|
||||
@@ -53,6 +51,7 @@ typedef void (*wxAnyClassInfo)();
|
||||
//
|
||||
class WXDLLIMPEXP_BASE wxAnyValueType
|
||||
{
|
||||
WX_DECLARE_ABSTRACT_TYPEINFO(wxAnyValueType)
|
||||
public:
|
||||
/**
|
||||
Default constructor.
|
||||
@@ -66,11 +65,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used for internal type matching.
|
||||
*/
|
||||
virtual wxAnyClassInfo GetClassInfo() const = 0;
|
||||
|
||||
/**
|
||||
This function is used for internal type matching.
|
||||
*/
|
||||
@@ -125,28 +119,22 @@ private:
|
||||
#define wxANY_VALUE_TYPE_CHECK_TYPE(valueTypePtr, T) \
|
||||
wxAnyValueTypeImpl<T>::IsSameClass(valueTypePtr)
|
||||
|
||||
//valueTypePtr->CheckType(static_cast<T*>(NULL))
|
||||
|
||||
|
||||
/**
|
||||
Helper macro for defining user value types.
|
||||
|
||||
NB: We really cannot compare sm_classInfo directly in IsSameClass(),
|
||||
but instead call sm_instance->GetClassInfo(). The former technique
|
||||
broke at least on GCC 4.2 (but worked on VC8 shared build).
|
||||
Even though C++ RTTI would be fully available to use, we'd have to to
|
||||
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.
|
||||
*/
|
||||
#define WX_DECLARE_ANY_VALUE_TYPE(CLS) \
|
||||
friend class wxAny; \
|
||||
WX_DECLARE_TYPEINFO_INLINE(CLS) \
|
||||
public: \
|
||||
static void sm_classInfo() {} \
|
||||
\
|
||||
virtual wxAnyClassInfo GetClassInfo() const \
|
||||
{ \
|
||||
return sm_classInfo; \
|
||||
} \
|
||||
static bool IsSameClass(const wxAnyValueType* otherType) \
|
||||
{ \
|
||||
return sm_instance->GetClassInfo() == otherType->GetClassInfo(); \
|
||||
return wxTypeId(*sm_instance) == wxTypeId(*otherType); \
|
||||
} \
|
||||
virtual bool IsSameType(const wxAnyValueType* otherType) const \
|
||||
{ \
|
||||
|
@@ -153,6 +153,8 @@ extern WXDLLIMPEXP_BASE wxEventType wxNewEventType();
|
||||
|
||||
#ifdef wxHAS_EVENT_BIND
|
||||
|
||||
#include "wx/typeinfo.h"
|
||||
|
||||
// The tag is a type associated to the event type (which is an integer itself,
|
||||
// in spite of its name) value. It exists in order to be used as a template
|
||||
// parameter and provide a mapping between the event type values and their
|
||||
@@ -189,16 +191,6 @@ typedef void (wxEvtHandler::*wxEventFunction)(wxEvent&);
|
||||
// compiler we can restore its old definition for it.
|
||||
typedef wxEventFunction wxObjectEventFunction;
|
||||
|
||||
|
||||
// wxEventFunctorClassInfo is used as a unique identifier for wxEventFunctor-
|
||||
// derived classes; it is more light weight than wxClassInfo and can be used in
|
||||
// template classes
|
||||
typedef void (*wxEventFunctorClassInfo)();
|
||||
|
||||
// this macro must be used in wxEventFunctor-derived classes
|
||||
#define wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( classInfoName ) \
|
||||
static void classInfoName() {}
|
||||
|
||||
// The event functor which is stored in the static and dynamic event tables:
|
||||
class WXDLLIMPEXP_BASE wxEventFunctor
|
||||
{
|
||||
@@ -212,11 +204,6 @@ public:
|
||||
// finding it in an event table in Unbind(), by the given functor:
|
||||
virtual bool IsMatching(const wxEventFunctor& functor) const = 0;
|
||||
|
||||
// Test whether the given class info is the same as from this functor. This
|
||||
// allows us in IsMatching to safely downcast the given wxEventFunctor without
|
||||
// the usage of dynamic_cast<>().
|
||||
virtual bool IsSameClass(wxEventFunctorClassInfo classInfo) const = 0;
|
||||
|
||||
// If the functor holds an wxEvtHandler, then get access to it and track
|
||||
// its lifetime with wxEventConnectionRef:
|
||||
virtual wxEvtHandler *GetEvtHandler() const
|
||||
@@ -228,6 +215,9 @@ public:
|
||||
// wxEventFunction:
|
||||
virtual wxEventFunction GetEvtMethod() const
|
||||
{ return NULL; }
|
||||
|
||||
private:
|
||||
WX_DECLARE_ABSTRACT_TYPEINFO(wxEventFunctor)
|
||||
};
|
||||
|
||||
// A plain method functor for the untyped legacy event types:
|
||||
@@ -247,7 +237,7 @@ public:
|
||||
|
||||
virtual bool IsMatching(const wxEventFunctor& functor) const
|
||||
{
|
||||
if ( functor.IsSameClass( sm_classInfo ))
|
||||
if ( wxTypeId(functor) == wxTypeId(*this) )
|
||||
{
|
||||
const wxObjectEventFunctor &other =
|
||||
static_cast< const wxObjectEventFunctor & >( functor );
|
||||
@@ -262,9 +252,6 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
|
||||
{ return sm_classInfo == otherClassInfo; }
|
||||
|
||||
virtual wxEvtHandler *GetEvtHandler() const
|
||||
{ return m_handler; }
|
||||
|
||||
@@ -275,7 +262,10 @@ private:
|
||||
wxEvtHandler *m_handler;
|
||||
wxEventFunction m_method;
|
||||
|
||||
wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
|
||||
// Provide a dummy default ctor for type info purposes
|
||||
wxObjectEventFunctor() { }
|
||||
|
||||
WX_DECLARE_TYPEINFO_INLINE(wxObjectEventFunctor)
|
||||
};
|
||||
|
||||
// Create a functor for the legacy events: used by Connect()
|
||||
@@ -424,22 +414,19 @@ public:
|
||||
|
||||
virtual bool IsMatching(const wxEventFunctor& functor) const
|
||||
{
|
||||
if ( !functor.IsSameClass(sm_classInfo) )
|
||||
if ( wxTypeId(functor) != wxTypeId(*this) )
|
||||
return false;
|
||||
|
||||
typedef wxEventFunctorMethod<EventTag, Class, EventArg, EventHandler>
|
||||
ThisFunctor;
|
||||
|
||||
// the cast is valid because IsSameClass() returned true above
|
||||
// the cast is valid because wxTypeId()s matched above
|
||||
const ThisFunctor& other = static_cast<const ThisFunctor &>(functor);
|
||||
|
||||
return (m_method == other.m_method || other.m_method == NULL) &&
|
||||
(m_handler == other.m_handler || other.m_handler == NULL);
|
||||
}
|
||||
|
||||
virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
|
||||
{ return sm_classInfo == otherClassInfo; }
|
||||
|
||||
virtual wxEvtHandler *GetEvtHandler() const
|
||||
{ return this->ConvertToEvtHandler(m_handler); }
|
||||
|
||||
@@ -450,7 +437,12 @@ private:
|
||||
EventHandler *m_handler;
|
||||
void (Class::*m_method)(EventArg&);
|
||||
|
||||
wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
|
||||
// Provide a dummy default ctor for type info purposes
|
||||
wxEventFunctorMethod() { }
|
||||
|
||||
typedef wxEventFunctorMethod<EventTag, Class,
|
||||
EventArg, EventHandler> thisClass;
|
||||
WX_DECLARE_TYPEINFO_INLINE(thisClass)
|
||||
};
|
||||
|
||||
|
||||
@@ -488,7 +480,7 @@ public:
|
||||
|
||||
virtual bool IsMatching(const wxEventFunctor &functor) const
|
||||
{
|
||||
if ( !functor.IsSameClass(sm_classInfo) )
|
||||
if ( wxTypeId(functor) != wxTypeId(*this) )
|
||||
return false;
|
||||
|
||||
typedef wxEventFunctorFunction<EventTag, EventArg> ThisFunctor;
|
||||
@@ -498,13 +490,14 @@ public:
|
||||
return m_handler == other.m_handler;
|
||||
}
|
||||
|
||||
virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
|
||||
{ return sm_classInfo == otherClassInfo; }
|
||||
|
||||
private:
|
||||
void (*m_handler)(EventArg&);
|
||||
|
||||
wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
|
||||
// Provide a dummy default ctor for type info purposes
|
||||
wxEventFunctorFunction() { }
|
||||
|
||||
typedef wxEventFunctorFunction<EventTag, EventArg> thisClass;
|
||||
WX_DECLARE_TYPEINFO_INLINE(thisClass)
|
||||
};
|
||||
|
||||
|
||||
@@ -532,7 +525,7 @@ public:
|
||||
|
||||
virtual bool IsMatching(const wxEventFunctor &functor) const
|
||||
{
|
||||
if ( !functor.IsSameClass(sm_classInfo) )
|
||||
if ( wxTypeId(functor) != wxTypeId(*this) )
|
||||
return false;
|
||||
|
||||
typedef wxEventFunctorFunctor<EventTag, Functor> FunctorThis;
|
||||
@@ -544,9 +537,6 @@ public:
|
||||
return m_handlerAddr == other.m_handlerAddr;
|
||||
}
|
||||
|
||||
virtual bool IsSameClass( wxEventFunctorClassInfo otherClassInfo ) const
|
||||
{ return sm_classInfo == otherClassInfo; }
|
||||
|
||||
private:
|
||||
// Store a copy of the functor to prevent using/calling an already
|
||||
// destroyed instance:
|
||||
@@ -555,7 +545,11 @@ private:
|
||||
// Use the address of the original functor for comparison in IsMatching:
|
||||
const void *m_handlerAddr;
|
||||
|
||||
wxDEFINE_EVENT_FUNCTOR_CLASS_INFO( sm_classInfo );
|
||||
// Provide a dummy default ctor for type info purposes
|
||||
wxEventFunctorFunctor() { }
|
||||
|
||||
typedef wxEventFunctorFunctor<EventTag, Functor> thisClass;
|
||||
WX_DECLARE_TYPEINFO_INLINE(thisClass)
|
||||
};
|
||||
|
||||
// Create functors for the templatized events, either allocated on the heap for
|
||||
|
123
include/wx/typeinfo.h
Normal file
123
include/wx/typeinfo.h
Normal file
@@ -0,0 +1,123 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Name: wx/typeinfo.h
|
||||
// Purpose: wxTypeId implementation
|
||||
// Author: Jaakko Salli
|
||||
// Created: 2009-11-19
|
||||
// RCS-ID: $Id$
|
||||
// Copyright: (c) wxWidgets Team
|
||||
// Licence: wxWindows licence
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _WX_TYPEINFO_H_
|
||||
#define _WX_TYPEINFO_H_
|
||||
|
||||
//
|
||||
// This file defines wxTypeId macro that should be used internally in
|
||||
// wxWidgets instead of typeid(), for compatibility with builds that do
|
||||
// not implement C++ RTTI. Also, type defining macros in this file are also
|
||||
// intended for internal use only at this time and may change in future
|
||||
// versions.
|
||||
//
|
||||
|
||||
#include "wx/defs.h"
|
||||
|
||||
#ifndef wxNO_RTTI
|
||||
|
||||
#include <typeinfo>
|
||||
#include <string.h>
|
||||
|
||||
#define _WX_DECLARE_TYPEINFO_CUSTOM(CLS, IDENTFUNC)
|
||||
#define WX_DECLARE_TYPEINFO_INLINE(CLS)
|
||||
#define WX_DECLARE_TYPEINFO(CLS)
|
||||
#define WX_DEFINE_TYPEINFO(CLS)
|
||||
#define WX_DECLARE_ABSTRACT_TYPEINFO(CLS)
|
||||
|
||||
//
|
||||
// For improved type-safety, let's make the check using class name
|
||||
// comparison. Most modern compilers already do this, but we cannot
|
||||
// rely on all supported compilers to work this well. However, in
|
||||
// cases where we'd know that typeid() would be flawless (as such),
|
||||
// wxTypeId could of course simply be defined as typeid.
|
||||
//
|
||||
|
||||
class wxTypeInfo
|
||||
{
|
||||
public:
|
||||
wxTypeInfo(const char* className)
|
||||
{
|
||||
m_className = className;
|
||||
}
|
||||
|
||||
bool operator==(const wxTypeInfo& other)
|
||||
{
|
||||
return strcmp(m_className, other.m_className) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const wxTypeInfo& other)
|
||||
{
|
||||
return strcmp(m_className, other.m_className) != 0;
|
||||
}
|
||||
private:
|
||||
const char* m_className;
|
||||
};
|
||||
|
||||
#define wxTypeId(OBJ) wxTypeInfo(typeid(OBJ).name())
|
||||
|
||||
#else // if !wxNO_RTTI
|
||||
|
||||
//
|
||||
// When C++ RTTI is not available, we will have to make the type comparison
|
||||
// using pointer to a dummy static member function. This will fail if
|
||||
// declared type is used across DLL boundaries, although using
|
||||
// WX_DECLARE_TYPEINFO() and WX_DEFINE_TYPEINFO() pair instead of
|
||||
// WX_DECLARE_TYPEINFO_INLINE() should fix this. However, that approach is
|
||||
// usually not possible when type info needs to be declared for a template
|
||||
// class.
|
||||
//
|
||||
|
||||
typedef void (*wxTypeIdentifier)();
|
||||
|
||||
// Use this macro to declare type info with specified static function
|
||||
// IDENTFUNC used as type identifier. Usually you should only use
|
||||
// WX_DECLARE_TYPEINFO() or WX_DECLARE_TYPEINFO_INLINE() however.
|
||||
#define _WX_DECLARE_TYPEINFO_CUSTOM(CLS, IDENTFUNC) \
|
||||
public: \
|
||||
virtual wxTypeIdentifier GetWxTypeId() const \
|
||||
{ \
|
||||
return reinterpret_cast<wxTypeIdentifier> \
|
||||
(&IDENTFUNC); \
|
||||
}
|
||||
|
||||
// Use this macro to declare type info with externally specified
|
||||
// type identifier, defined with WX_DEFINE_TYPEINFO().
|
||||
#define WX_DECLARE_TYPEINFO(CLS) \
|
||||
private: \
|
||||
static CLS sm_wxClassInfo(); \
|
||||
_WX_DECLARE_TYPEINFO_CUSTOM(CLS, sm_wxClassInfo)
|
||||
|
||||
// Use this macro to implement type identifier function required by
|
||||
// WX_DECLARE_TYPEINFO().
|
||||
// NOTE: CLS is required to have default ctor. If it doesn't
|
||||
// already, you should provide a private dummy one.
|
||||
#define WX_DEFINE_TYPEINFO(CLS) \
|
||||
CLS CLS::sm_wxClassInfo() { return CLS(); }
|
||||
|
||||
// Use this macro to declare type info fully inline in class.
|
||||
// NOTE: CLS is required to have default ctor. If it doesn't
|
||||
// already, you should provide a private dummy one.
|
||||
#define WX_DECLARE_TYPEINFO_INLINE(CLS) \
|
||||
private: \
|
||||
static CLS sm_wxClassInfo() { return CLS(); } \
|
||||
_WX_DECLARE_TYPEINFO_CUSTOM(CLS, sm_wxClassInfo)
|
||||
|
||||
#define wxTypeId(OBJ) (OBJ).GetWxTypeId()
|
||||
|
||||
// Because abstract classes cannot be instantiated, we use
|
||||
// this macro to define pure virtual type interface for them.
|
||||
#define WX_DECLARE_ABSTRACT_TYPEINFO(CLS) \
|
||||
public: \
|
||||
virtual wxTypeIdentifier GetWxTypeId() const = 0;
|
||||
|
||||
#endif // wxNO_RTTI/!wxNO_RTTI
|
||||
|
||||
#endif // _WX_TYPEINFO_H_
|
Reference in New Issue
Block a user