hashset.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name: wx/hashset.h
  3. // Purpose: wxHashSet class
  4. // Author: Mattia Barbon
  5. // Modified by:
  6. // Created: 11/08/2003
  7. // Copyright: (c) Mattia Barbon
  8. // Licence: wxWindows licence
  9. /////////////////////////////////////////////////////////////////////////////
  10. #ifndef _WX_HASHSET_H_
  11. #define _WX_HASHSET_H_
  12. #include "wx/hashmap.h"
  13. // see comment in wx/hashmap.h which also applies to different standard hash
  14. // set classes
  15. #if wxUSE_STD_CONTAINERS && \
  16. (defined(HAVE_STD_UNORDERED_SET) || defined(HAVE_TR1_UNORDERED_SET))
  17. #if defined(HAVE_STD_UNORDERED_SET)
  18. #include <unordered_set>
  19. #define WX_HASH_SET_BASE_TEMPLATE std::unordered_set
  20. #elif defined(HAVE_TR1_UNORDERED_SET)
  21. #include <tr1/unordered_set>
  22. #define WX_HASH_SET_BASE_TEMPLATE std::tr1::unordered_set
  23. #else
  24. #error Update this code: unordered_set is available, but I do not know where.
  25. #endif
  26. #elif wxUSE_STD_CONTAINERS && defined(HAVE_STL_HASH_MAP)
  27. #if defined(HAVE_EXT_HASH_MAP)
  28. #include <ext/hash_set>
  29. #elif defined(HAVE_HASH_MAP)
  30. #include <hash_set>
  31. #endif
  32. #define WX_HASH_SET_BASE_TEMPLATE WX_HASH_MAP_NAMESPACE::hash_set
  33. #endif // different hash_set/unordered_set possibilities
  34. #ifdef WX_HASH_SET_BASE_TEMPLATE
  35. // we need to define the class declared by _WX_DECLARE_HASH_SET as a class and
  36. // not a typedef to allow forward declaring it
  37. #define _WX_DECLARE_HASH_SET_IMPL( KEY_T, HASH_T, KEY_EQ_T, PTROP, CLASSNAME, CLASSEXP ) \
  38. CLASSEXP CLASSNAME \
  39. : public WX_HASH_SET_BASE_TEMPLATE< KEY_T, HASH_T, KEY_EQ_T > \
  40. { \
  41. public: \
  42. explicit CLASSNAME(size_type n = 3, \
  43. const hasher& h = hasher(), \
  44. const key_equal& ke = key_equal(), \
  45. const allocator_type& a = allocator_type()) \
  46. : WX_HASH_SET_BASE_TEMPLATE< KEY_T, HASH_T, KEY_EQ_T >(n, h, ke, a) \
  47. {} \
  48. template <class InputIterator> \
  49. CLASSNAME(InputIterator f, InputIterator l, \
  50. const hasher& h = hasher(), \
  51. const key_equal& ke = key_equal(), \
  52. const allocator_type& a = allocator_type()) \
  53. : WX_HASH_SET_BASE_TEMPLATE< KEY_T, HASH_T, KEY_EQ_T >(f, l, h, ke, a)\
  54. {} \
  55. CLASSNAME(const WX_HASH_SET_BASE_TEMPLATE< KEY_T, HASH_T, KEY_EQ_T >& s) \
  56. : WX_HASH_SET_BASE_TEMPLATE< KEY_T, HASH_T, KEY_EQ_T >(s) \
  57. {} \
  58. }
  59. // In some standard library implementations (in particular, the libstdc++ that
  60. // ships with g++ 4.7), std::unordered_set inherits privately from its hasher
  61. // and comparator template arguments for purposes of empty base optimization.
  62. // As a result, in the declaration of a class deriving from std::unordered_set
  63. // the names of the hasher and comparator classes are interpreted as naming
  64. // the base class which is inaccessible.
  65. // The workaround is to prefix the class names with 'struct'; however, don't
  66. // do this on MSVC because it causes a warning there if the class was
  67. // declared as a 'class' rather than a 'struct' (and MSVC's std::unordered_set
  68. // implementation does not suffer from the access problem).
  69. #ifdef _MSC_VER
  70. #define WX_MAYBE_PREFIX_WITH_STRUCT(STRUCTNAME) STRUCTNAME
  71. #else
  72. #define WX_MAYBE_PREFIX_WITH_STRUCT(STRUCTNAME) struct STRUCTNAME
  73. #endif
  74. #define _WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, PTROP, CLASSNAME, CLASSEXP ) \
  75. _WX_DECLARE_HASH_SET_IMPL( \
  76. KEY_T, \
  77. WX_MAYBE_PREFIX_WITH_STRUCT(HASH_T), \
  78. WX_MAYBE_PREFIX_WITH_STRUCT(KEY_EQ_T), \
  79. PTROP, \
  80. CLASSNAME, \
  81. CLASSEXP)
  82. #else // no appropriate STL class, use our own implementation
  83. // this is a complex way of defining an easily inlineable identity function...
  84. #define _WX_DECLARE_HASH_SET_KEY_EX( KEY_T, CLASSNAME, CLASSEXP ) \
  85. CLASSEXP CLASSNAME \
  86. { \
  87. typedef KEY_T key_type; \
  88. typedef const key_type const_key_type; \
  89. typedef const_key_type& const_key_reference; \
  90. public: \
  91. CLASSNAME() { } \
  92. const_key_reference operator()( const_key_reference key ) const \
  93. { return key; } \
  94. \
  95. /* the dummy assignment operator is needed to suppress compiler */ \
  96. /* warnings from hash table class' operator=(): gcc complains about */ \
  97. /* "statement with no effect" without it */ \
  98. CLASSNAME& operator=(const CLASSNAME&) { return *this; } \
  99. };
  100. #define _WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, PTROP, CLASSNAME, CLASSEXP )\
  101. _WX_DECLARE_HASH_SET_KEY_EX( KEY_T, CLASSNAME##_wxImplementation_KeyEx, CLASSEXP ) \
  102. _WX_DECLARE_HASHTABLE( KEY_T, KEY_T, HASH_T, \
  103. CLASSNAME##_wxImplementation_KeyEx, KEY_EQ_T, PTROP, \
  104. CLASSNAME##_wxImplementation_HashTable, CLASSEXP, grow_lf70, never_shrink ) \
  105. CLASSEXP CLASSNAME:public CLASSNAME##_wxImplementation_HashTable \
  106. { \
  107. public: \
  108. _WX_DECLARE_PAIR( iterator, bool, Insert_Result, CLASSEXP ) \
  109. \
  110. wxEXPLICIT CLASSNAME( size_type hint = 100, hasher hf = hasher(), \
  111. key_equal eq = key_equal() ) \
  112. : CLASSNAME##_wxImplementation_HashTable( hint, hf, eq, \
  113. CLASSNAME##_wxImplementation_KeyEx() ) {} \
  114. \
  115. Insert_Result insert( const key_type& key ) \
  116. { \
  117. bool created; \
  118. Node *node = GetOrCreateNode( key, created ); \
  119. return Insert_Result( iterator( node, this ), created ); \
  120. } \
  121. \
  122. const_iterator find( const const_key_type& key ) const \
  123. { \
  124. return const_iterator( GetNode( key ), this ); \
  125. } \
  126. \
  127. iterator find( const const_key_type& key ) \
  128. { \
  129. return iterator( GetNode( key ), this ); \
  130. } \
  131. \
  132. size_type erase( const key_type& k ) \
  133. { return CLASSNAME##_wxImplementation_HashTable::erase( k ); } \
  134. void erase( const iterator& it ) { erase( *it ); } \
  135. void erase( const const_iterator& it ) { erase( *it ); } \
  136. \
  137. /* count() == 0 | 1 */ \
  138. size_type count( const const_key_type& key ) const \
  139. { return GetNode( key ) ? 1 : 0; } \
  140. }
  141. #endif // STL/wx implementations
  142. // these macros are to be used in the user code
  143. #define WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, CLASSNAME) \
  144. _WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, wxPTROP_NORMAL, CLASSNAME, class )
  145. // and these do exactly the same thing but should be used inside the
  146. // library
  147. #define WX_DECLARE_HASH_SET_WITH_DECL( KEY_T, HASH_T, KEY_EQ_T, CLASSNAME, DECL) \
  148. _WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, wxPTROP_NORMAL, CLASSNAME, DECL )
  149. #define WX_DECLARE_EXPORTED_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, CLASSNAME) \
  150. WX_DECLARE_HASH_SET_WITH_DECL( KEY_T, HASH_T, KEY_EQ_T, \
  151. CLASSNAME, class WXDLLIMPEXP_CORE )
  152. // Finally these versions allow to define hash sets of non-objects (including
  153. // pointers, hence the confusing but wxArray-compatible name) without
  154. // operator->() which can't be used for them. This is mostly used inside the
  155. // library itself to avoid warnings when using such hash sets with some less
  156. // common compilers (notably Sun CC).
  157. #define WX_DECLARE_HASH_SET_PTR( KEY_T, HASH_T, KEY_EQ_T, CLASSNAME) \
  158. _WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, wxPTROP_NOP, CLASSNAME, class )
  159. #define WX_DECLARE_HASH_SET_WITH_DECL_PTR( KEY_T, HASH_T, KEY_EQ_T, CLASSNAME, DECL) \
  160. _WX_DECLARE_HASH_SET( KEY_T, HASH_T, KEY_EQ_T, wxPTROP_NOP, CLASSNAME, DECL )
  161. // delete all hash elements
  162. //
  163. // NB: the class declaration of the hash elements must be visible from the
  164. // place where you use this macro, otherwise the proper destructor may not
  165. // be called (a decent compiler should give a warning about it, but don't
  166. // count on it)!
  167. #define WX_CLEAR_HASH_SET(type, hashset) \
  168. { \
  169. type::iterator it, en; \
  170. for( it = (hashset).begin(), en = (hashset).end(); it != en; ++it ) \
  171. delete *it; \
  172. (hashset).clear(); \
  173. }
  174. #endif // _WX_HASHSET_H_