X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/c0089c96ecb12ae0ad48545337d2e47ce3a9f37a..d8f2f99ff72b7aa656765799936f0a1038cf3a8b:/include/wx/list.h diff --git a/include/wx/list.h b/include/wx/list.h index fb597e90aa..8c19a070ec 100644 --- a/include/wx/list.h +++ b/include/wx/list.h @@ -135,17 +135,54 @@ 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 */ \ @@ -156,7 +193,7 @@ private: 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 +203,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 +227,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 +262,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 +311,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,7 +330,8 @@ 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 */ \ @@ -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: \