X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8907154c1a8a6882c6797d1f16393ddfb23e7f3a..ba5787676d002f76b4c3944cb598b626f10f058d:/include/wx/list.h diff --git a/include/wx/list.h b/include/wx/list.h index b1f5d93a9c..a2907d0693 100644 --- a/include/wx/list.h +++ b/include/wx/list.h @@ -1,5 +1,5 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: list.h +// Name: wx/list.h // Purpose: wxList, wxStringList classes // Author: Julian Smart // Modified by: VZ at 16/11/98: WX_DECLARE_LIST() and typesafe lists added @@ -135,28 +135,67 @@ private: #endif // defined( __VISUALC__ ) +/* + Note 1: the outer helper class _WX_LIST_HELPER_##liT below is a workaround + for mingw 3.2.3 compiler bug that prevents a static function of liT class + from being exported into dll. A minimal code snippet reproducing the bug: + + struct WXDLLEXPORT Foo + { + static void Bar(); + struct SomeInnerClass + { + friend class Foo; // comment this out to make it link + }; + ~Foo() + { + Bar(); + } + }; + + The program does not link under mingw_gcc 3.2.3 producing undefined + reference to Foo::Bar() function + + + Note 2: the EmptyList is needed to allow having a NULL pointer-like + invalid iterator. We used to use just an uninitialized iterator object + instead but this fails with some debug/checked versions of STL, notably the + glibc version activated with _GLIBCXX_DEBUG, so we need to have a separate + invalid iterator. + */ + +// the real wxList-class declaration #define WX_DECLARE_LIST_XO(elT, liT, decl) \ + decl _WX_LIST_HELPER_##liT \ + { \ + typedef elT _WX_LIST_ITEM_TYPE_##liT; \ + public: \ + static void DeleteFunction( _WX_LIST_ITEM_TYPE_##liT X ); \ + }; \ + \ VC6_WORKAROUND(elT, liT, decl) \ decl liT : public std::list \ { \ private: \ + typedef std::list BaseListType; \ + static BaseListType EmptyList; \ + \ bool m_destroy; \ - private: \ - typedef elT _WX_LIST_ITEM_TYPE_##liT; \ - static void DeleteFunction( const _WX_LIST_ITEM_TYPE_##liT X ); \ + \ public: \ - class compatibility_iterator \ + decl compatibility_iterator \ { \ private: \ - /* Workaround for broken VC6 nested class name resolution */ \ - typedef std::list::iterator iterator; \ - friend class liT; \ - private: \ + /* Workaround for broken VC6 nested class name resolution */ \ + typedef std::list::iterator iterator; \ + friend class liT; \ + \ iterator m_iter; \ liT * m_list; \ + \ public: \ compatibility_iterator() \ - : m_iter(), m_list( NULL ) {} \ + : m_iter(EmptyList.end()), m_list( NULL ) {} \ compatibility_iterator( liT* li, iterator i ) \ : m_iter( i ), m_list( li ) {} \ compatibility_iterator( const liT* li, iterator i ) \ @@ -166,7 +205,11 @@ private: const compatibility_iterator* operator->() const { return this; } \ \ bool operator==(const compatibility_iterator& i) const \ - { return (m_list == i.m_list) && (m_iter == i.m_iter); } \ + { \ + wxASSERT_MSG( m_list && i.m_list, \ + _T("comparing invalid iterators is illegal") ); \ + return (m_list == i.m_list) && (m_iter == i.m_iter); \ + } \ bool operator!=(const compatibility_iterator& i) const \ { return !( operator==( i ) ); } \ operator bool() const \ @@ -186,16 +229,16 @@ private: } \ compatibility_iterator GetPrevious() const \ { \ + if ( m_iter == m_list->begin() ) \ + return compatibility_iterator(); \ + \ iterator i = m_iter; \ return compatibility_iterator( m_list, --i ); \ } \ int IndexOf() const \ { \ - return m_list ? \ - m_iter != m_list->end() ? \ - std::distance( m_list->begin(), m_iter ) : \ - wxNOT_FOUND : \ - wxNOT_FOUND; \ + return *this ? std::distance( m_list->begin(), m_iter ) \ + : wxNOT_FOUND; \ } \ }; \ public: \ @@ -221,6 +264,11 @@ private: std::advance( i, idx ); \ return compatibility_iterator( this, i ); \ } \ + elT operator[](size_t idx) const \ + { \ + return Item(idx).GetData(); \ + } \ + \ compatibility_iterator GetFirst() const \ { \ return compatibility_iterator( this, \ @@ -265,7 +313,7 @@ private: void Erase( const compatibility_iterator& i ) \ { \ if ( m_destroy ) \ - DeleteFunction( i->GetData() ); \ + _WX_LIST_HELPER_##liT::DeleteFunction( i->GetData() ); \ erase( i.m_iter ); \ } \ bool DeleteNode( const compatibility_iterator& i ) \ @@ -284,13 +332,17 @@ private: void Clear() \ { \ if ( m_destroy ) \ - std::for_each( begin(), end(), DeleteFunction ); \ + std::for_each( begin(), end(), \ + _WX_LIST_HELPER_##liT::DeleteFunction ); \ clear(); \ } \ /* Workaround for broken VC6 std::list::sort() see above */ \ void Sort( wxSortCompareFunction compfunc ) \ { sort( WX_LIST_SORTFUNCTION( elT, compfunc ) ); } \ ~liT() { Clear(); } \ + \ + /* It needs access to our EmptyList */ \ + friend decl compatibility_iterator; \ } #define WX_DECLARE_LIST(elementtype, listname) \ @@ -309,7 +361,7 @@ private: WX_DECLARE_USER_EXPORTED_LIST(elementtype, listname, usergoo) // this macro must be inserted in your program after -// #include +// #include "wx/listimpl.cpp" #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!" #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name) @@ -317,11 +369,6 @@ private: #else // if !wxUSE_STL -// due to circular header dependencies this function has to be declared here -// (normally it's found in utils.h which includes itself list.h...) -#if WXWIN_COMPATIBILITY_2_4 -extern WXDLLIMPEXP_BASE wxChar* copystring(const wxChar *s); -#endif // undef it to get rid of old, deprecated functions #define wxLIST_COMPATIBILITY @@ -676,7 +723,17 @@ private: { \ public: \ typedef nodetype Node; \ - typedef Node* compatibility_iterator; \ + classexp compatibility_iterator \ + { \ + public: \ + compatibility_iterator(Node *ptr = NULL) : m_ptr(ptr) { } \ + \ + Node *operator->() const { return m_ptr; } \ + operator Node *() const { return m_ptr; } \ + \ + private: \ + Node *m_ptr; \ + }; \ \ name(wxKeyType keyType = wxKEY_NONE) : wxListBase(keyType) \ { } \ @@ -722,7 +779,7 @@ private: { return wxListBase::DeleteNode(node); } \ bool DeleteObject(Tbase *object) \ { return wxListBase::DeleteObject(object); } \ - void Erase(compatibility_iterator it) \ + void Erase(nodetype *it) \ { DeleteNode(it); } \ \ nodetype *Find(const Tbase *object) const \ @@ -759,7 +816,7 @@ private: typedef base_value_type& base_reference; \ typedef const base_value_type& const_base_reference; \ \ - class iterator \ + classexp iterator \ { \ typedef name list; \ public: \ @@ -799,7 +856,7 @@ private: bool operator==(const itor& it) const \ { return it.m_node == m_node; } \ }; \ - class const_iterator \ + classexp const_iterator \ { \ typedef name list; \ public: \ @@ -842,7 +899,7 @@ private: bool operator==(const itor& it) const \ { return it.m_node == m_node; } \ }; \ - class reverse_iterator \ + classexp reverse_iterator \ { \ typedef name list; \ public: \ @@ -881,7 +938,7 @@ private: bool operator==(const itor& it) const \ { return it.m_node == m_node; } \ }; \ - class const_reverse_iterator \ + classexp const_reverse_iterator \ { \ typedef name list; \ public: \ @@ -1064,7 +1121,7 @@ private: WX_DECLARE_LIST_PTR_2(elementtype, listname, wx##listname##Node, class usergoo) // this macro must be inserted in your program after -// #include +// #include "wx/listimpl.cpp" #define WX_DEFINE_LIST(name) "don't forget to include listimpl.cpp!" #define WX_DEFINE_EXPORTED_LIST(name) WX_DEFINE_LIST(name) @@ -1236,5 +1293,4 @@ public: (list).clear(); \ } -#endif - // _WX_LISTH__ +#endif // _WX_LISTH__