X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/371a5b4e62eb415107e045588f614fa49e866e78..62c9b3d73fdf9a892a311241f1effc12dde0282a:/include/wx/ptr_scpd.h diff --git a/include/wx/ptr_scpd.h b/include/wx/ptr_scpd.h index b574491359..ffbb01105d 100644 --- a/include/wx/ptr_scpd.h +++ b/include/wx/ptr_scpd.h @@ -2,16 +2,17 @@ // Name: wx/ptr_scpd.h // Purpose: scoped smart pointer class // Author: Jesse Lovelace -// Modified by: +// Modified by: Vadim Zeitlin to add template wxScopedArray // Created: 06/01/02 // RCS-ID: $Id$ // Copyright: (c) Jesse Lovelace and original Boost authors (see below) +// (c) 2009 Vadim Zeitlin // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // This class closely follows the implementation of the boost -// library scoped_ptr and is an adaption for c++ macro's in -// the wxWindows project. The original authors of the boost +// library scoped_ptr and is an adaption for c++ macro's in +// the wxWidgets project. The original authors of the boost // scoped_ptr are given below with their respective copyrights. // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. @@ -30,33 +31,162 @@ #include "wx/defs.h" -/* checked deleters are used to make sure that the - type being deleted is really a complete type. - - Jesse Lovelace -*/ +// ---------------------------------------------------------------------------- +// wxScopedPtr: A scoped pointer +// ---------------------------------------------------------------------------- + +template +class wxScopedPtr +{ +public: + typedef T element_type; + + wxEXPLICIT wxScopedPtr(T * ptr = NULL) : m_ptr(ptr) { } + + ~wxScopedPtr() { delete m_ptr; } -#define wxCHECKED_DELETE(ptr) \ - if (true) { \ - typedef char complete[sizeof(*ptr)]; \ - delete ptr; \ + // test for pointer validity: defining conversion to unspecified_bool_type + // and not more obvious bool to avoid implicit conversions to integer types + typedef T *(wxScopedPtr::*unspecified_bool_type)() const; + operator unspecified_bool_type() const + { + return m_ptr ? &wxScopedPtr::get : NULL; } -#define wxCHECKED_DELETE_ARRAY(ptr) \ - if (true) { \ - typedef char complete[sizeof(*ptr)]; \ - delete [] ptr; \ + void reset(T * ptr = NULL) + { + if ( ptr != m_ptr ) + { + delete m_ptr; + m_ptr = ptr; + } } -/* These scoped pointers are *not* assignable and cannot be used - within a container. Look for wxDECLARE_SHARED_PTR for this - functionality. + T *release() + { + T *ptr = m_ptr; + m_ptr = NULL; + return ptr; + } - In addition, the type being used *must* be complete at the time - that wxDEFINE_SCOPED_* is called or a compiler error will result. - This is because the class checks for the completeness of the type - being used. + T & operator*() const + { + wxASSERT(m_ptr != NULL); + return *m_ptr; + } + + T * operator->() const + { + wxASSERT(m_ptr != NULL); + return m_ptr; + } + + T * get() const + { + return m_ptr; + } + + void swap(wxScopedPtr& other) + { + T * const tmp = other.m_ptr; + other.m_ptr = m_ptr; + m_ptr = tmp; + } + +private: + T * m_ptr; + + DECLARE_NO_COPY_TEMPLATE_CLASS(wxScopedPtr, T) +}; + +// ---------------------------------------------------------------------------- +// wxScopedArray: A scoped array +// ---------------------------------------------------------------------------- + +template +class wxScopedArray +{ +public: + typedef T element_type; + + wxEXPLICIT wxScopedArray(T * array = NULL) : m_array(array) { } + + ~wxScopedArray() { delete [] m_array; } + + // test for pointer validity: defining conversion to unspecified_bool_type + // and not more obvious bool to avoid implicit conversions to integer types + typedef T *(wxScopedArray::*unspecified_bool_type)() const; + operator unspecified_bool_type() const + { + return m_array ? &wxScopedArray::get : NULL; + } + + void reset(T *array = NULL) + { + if ( array != m_array ) + { + delete m_array; + m_array = array; + } + } + + T& operator[](size_t n) const { return m_array[n]; } + + T *get() const { return m_array; } + + void swap(wxScopedArray &other) + { + T * const tmp = other.m_array; + other.m_array = m_array; + m_array = tmp; + } + +private: + T *m_array; + + DECLARE_NO_COPY_TEMPLATE_CLASS(wxScopedArray, T) +}; + +// ---------------------------------------------------------------------------- +// old macro based implementation +// ---------------------------------------------------------------------------- + +/* + checked deleters are used to make sure that the type being deleted is really + a complete type.: otherwise sizeof() would result in a compile-time error + + do { ... } while ( 0 ) construct is used to have an anonymous scope + (otherwise we could have name clashes between different "complete"s) but + still force a semicolon after the macro */ +#ifdef __WATCOMC__ + #define wxFOR_ONCE(name) for(int name=0; name<1; name++) + #define wxPRE_NO_WARNING_SCOPE(name) wxFOR_ONCE(wxMAKE_UNIQUE_NAME(name)) + #define wxPOST_NO_WARNING_SCOPE(name) +#else + #define wxPRE_NO_WARNING_SCOPE(name) do + #define wxPOST_NO_WARNING_SCOPE(name) while ( wxFalse ) +#endif + +#define wxCHECKED_DELETE(ptr) \ + wxPRE_NO_WARNING_SCOPE(scope_var1) \ + { \ + typedef char complete[sizeof(*ptr)]; \ + delete ptr; \ + } wxPOST_NO_WARNING_SCOPE(scope_var1) + +#define wxCHECKED_DELETE_ARRAY(ptr) \ + wxPRE_NO_WARNING_SCOPE(scope_var2) \ + { \ + typedef char complete[sizeof(*ptr)]; \ + delete [] ptr; \ + } wxPOST_NO_WARNING_SCOPE(scope_var2) + +/* The type being used *must* be complete at the time + that wxDEFINE_SCOPED_* is called or a compiler error will result. + This is because the class checks for the completeness of the type + being used. */ #define wxDECLARE_SCOPED_PTR(T, name) \ class name \ @@ -68,7 +198,7 @@ private: \ name & operator=(name const &); \ \ public: \ - wxEXPLICIT name(T * ptr = NULL) \ + wxEXPLICIT name(T * ptr = NULL) \ : m_ptr(ptr) { } \ \ ~name(); \ @@ -82,6 +212,13 @@ public: \ } \ } \ \ + T *release() \ + { \ + T *ptr = m_ptr; \ + m_ptr = NULL; \ + return ptr; \ + } \ + \ T & operator*() const \ { \ wxASSERT(m_ptr != NULL); \ @@ -110,9 +247,17 @@ public: \ #define wxDEFINE_SCOPED_PTR(T, name)\ name::~name() \ { \ - wxCHECKED_DELETE(m_ptr) \ + wxCHECKED_DELETE(m_ptr); \ } +// this macro can be used for the most common case when you want to declare and +// define the scoped pointer at the same time and want to use the standard +// naming convention: auto pointer to Foo is called FooPtr +#define wxDEFINE_SCOPED_PTR_TYPE(T) \ + wxDECLARE_SCOPED_PTR(T, T ## Ptr) \ + wxDEFINE_SCOPED_PTR(T, T ## Ptr) + +// the same but for arrays instead of simple pointers #define wxDECLARE_SCOPED_ARRAY(T, name)\ class name \ { \ @@ -149,16 +294,44 @@ public: \ }; #define wxDEFINE_SCOPED_ARRAY(T, name) \ -name::~name() \ -{ \ - wxCHECKED_DELETE_ARRAY(m_ptr) \ -} \ -void name::reset(T * p){ \ - if (m_ptr != p) \ - { \ - wxCHECKED_DELETE_ARRAY(m_ptr); \ - m_ptr = p; \ - } \ +name::~name() \ +{ \ + wxCHECKED_DELETE_ARRAY(m_ptr); \ +} \ +void name::reset(T * p){ \ + if (m_ptr != p) \ + { \ + wxCHECKED_DELETE_ARRAY(m_ptr); \ + m_ptr = p; \ + } \ } -#endif +// ---------------------------------------------------------------------------- +// "Tied" scoped pointer: same as normal one but also sets the value of +// some other variable to the pointer value +// ---------------------------------------------------------------------------- + +#define wxDEFINE_TIED_SCOPED_PTR_TYPE(T) \ + wxDEFINE_SCOPED_PTR_TYPE(T) \ + class T ## TiedPtr : public T ## Ptr \ + { \ + public: \ + T ## TiedPtr(T **pp, T *p) \ + : T ## Ptr(p), m_pp(pp) \ + { \ + m_pOld = *pp; \ + *pp = p; \ + } \ + \ + ~ T ## TiedPtr() \ + { \ + *m_pp = m_pOld; \ + } \ + \ + private: \ + T **m_pp; \ + T *m_pOld; \ + }; + +#endif // __WX_SCOPED_POINTER__ +