Changeset 408 for trunk/nv/stl/unordered_map.hh
- Timestamp:
- 06/21/15 02:44:30 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/nv/stl/unordered_map.hh
r403 r408 17 17 #include <nv/stl/container/hash_table.hh> 18 18 #include <nv/stl/utility/pair.hh> 19 #include <nv/stl/functional/hash.hh> 20 #include <nv/stl/functional/comparisons.hh> 21 #include <nv/stl/memory.hh> 19 22 20 23 namespace nv … … 22 25 23 26 template < 27 typename T, 28 typename IsEqual = equal_to<T>, 29 bool IsEmpty = is_empty< IsEqual >::value 30 > 31 struct compare_policy; 32 33 34 template < typename T > 35 struct compare_policy< T, equal_to<T>, true > 36 { 37 constexpr bool compare( const T& t1, const T& t2 ) const 38 { 39 return t1 == t2; 40 } 41 equal_to<T> key_eq() const { return equal_to<T>(); } 42 }; 43 44 template < typename T, typename IsEqual > 45 struct compare_policy< T, IsEqual, true > : private IsEqual 46 { 47 constexpr bool compare( const T& t1, const T& t2 ) const 48 { 49 return ( *this )( t1 == t2 ); 50 } 51 IsEqual key_eq() const { return ( *this ); } 52 }; 53 54 template < typename T, typename IsEqual > 55 struct compare_policy< T, IsEqual, false > 56 { 57 constexpr bool compare( const T& t1, const T& t2 ) const 58 { 59 return m_key_eq( t1 == t2 ); 60 } 61 IsEqual key_eq() const { return m_key_eq; } 62 private: 63 IsEqual m_key_eq; 64 }; 65 66 template < 67 typename T, 68 typename H, 69 typename Hasher = hash< T, H >, 70 bool IsEmpty = is_empty< Hasher >::value 71 > 72 struct hash_policy; 73 74 75 template < typename T, typename H > 76 struct hash_policy< T, H, hash< T, H >, true > 77 { 78 constexpr H get_hash( const T& t ) const 79 { 80 return hash< T, H >::get( t ); 81 } 82 hash< T, H > hash_function() const { return hash< T, H >(); } 83 }; 84 85 template < typename T, typename H, typename Hasher > 86 struct hash_policy< T, H, Hasher, true > : private Hasher 87 { 88 constexpr H get_hash( const T& t ) const 89 { 90 return ( *this )( t ); 91 } 92 hash< T, H > hash_function() const { return ( *this ); } 93 }; 94 95 template < typename T, typename H, typename Hasher > 96 struct hash_policy< T, H, Hasher, false > 97 { 98 constexpr H get_hash( const T& t ) const 99 { 100 return m_hasher( t ); 101 } 102 hash< T, H > hash_function() const { return m_hasher; } 103 private: 104 Hasher m_hasher; 105 }; 106 107 // Due to MSVC not being able to handle multiple empty bases, if both 108 // hash and compare are empty, we will still get a 4-size structure. 109 // We will optimize here, to assure that if either is empty, we will still 110 // get an empty class 111 template < 112 typename T, 113 typename H, 114 typename IsEqual = equal_to< T >, 115 typename Hasher = hash< T, H >, 116 bool IsEqualIsEmpty = is_empty< IsEqual >::value, 117 bool HasherIsEmpty = is_empty< Hasher >::value 118 > 119 struct hash_compare_policy; 120 121 template < 122 typename T, 123 typename H, 124 typename IsEqual, 125 typename Hasher, 126 bool HasherIsEmpty 127 > 128 struct hash_compare_policy< T, H, IsEqual, Hasher, false, HasherIsEmpty > 129 : hash_policy< T, H, Hasher, HasherIsEmpty > 130 { 131 constexpr bool compare( const T& t1, const T& t2 ) const 132 { 133 return m_key_eq( t1 == t2 ); 134 } 135 IsEqual key_eq() const { return m_key_eq; } 136 private: 137 IsEqual m_key_eq; 138 }; 139 140 template < 141 typename T, 142 typename H, 143 typename IsEqual, 144 typename Hasher 145 > 146 struct hash_compare_policy< T, H, IsEqual, Hasher, true, false > 147 : compare_policy< T, IsEqual, true > 148 { 149 constexpr H get_hash( const T& t ) const 150 { 151 return m_hasher( t ); 152 } 153 hash< T, H > hash_function() const { return m_hasher; } 154 private: 155 Hasher m_hasher; 156 }; 157 158 template < 159 typename T, 160 typename H, 161 typename Hasher, 162 typename IsEqual 163 > 164 struct hash_compare_policy< T, H, IsEqual, Hasher, true, true > 165 : hash_policy< T, H, Hasher, true > 166 { 167 constexpr bool compare( const T& t1, const T& t2 ) const 168 { 169 static_assert( is_trivial< IsEqual >::value, "There is something really wrong with your equality functor." ); 170 return IsEqual()( t1, t2 ); 171 } 172 IsEqual key_eq() const { return IsEqual(); } 173 }; 174 175 template < 176 typename Key, 177 typename Value, 178 typename Hash, 179 typename IsEqual = equal_to< Key >, 180 typename Hasher = hash< Key, Hash > 181 > 182 struct hash_table_stl_map_policy : hash_compare_policy< Key, Hash, IsEqual, Hasher > 183 { 184 typedef hash_compare_policy< Key, Hash, IsEqual, Hasher > base_type; 185 186 typedef hash_table_standard_entry< Key, Value, Hash, false > entry_type; 187 typedef typename entry_type::key_type key_type; 188 typedef typename entry_type::mapped_type mapped_type; 189 typedef typename entry_type::hash_type hash_type; 190 typedef typename entry_type::value_type value_type; 191 typedef Key query_type; 192 193 constexpr bool entry_compare( const entry_type* entry, hash_type, const query_type& key ) const 194 { 195 return base_type::compare( entry_type::get_key( entry ), key ); 196 } 197 198 constexpr bool entry_compare( const entry_type* entry, hash_type, const value_type& value ) const 199 { 200 return base_type::compare( entry_type::get_key( entry ), entry_type::get_key( value ) ); 201 } 202 203 template < typename... Args > 204 static void entry_construct( entry_type* entry, hash_type, Args&&... params ) 205 { 206 construct_object( entry_type::get_value( entry ), ::nv::forward<Args>( params )... ); 207 } 208 209 static void entry_destroy( entry_type* entry ) 210 { 211 destroy_object( entry_type::get_value( entry ) ); 212 } 213 214 constexpr hash_type get_entry_hash( const entry_type* entry ) const 215 { 216 return base_type::get_hash( entry_type::get_key( entry ) ); 217 } 218 constexpr hash_type get_value_hash( const value_type& value ) const 219 { 220 return base_type::get_hash( entry_type::get_key( value ) ); 221 } 222 }; 223 224 template < 24 225 typename Key, 25 226 typename T, 26 227 typename Hash = hash< Key >, 27 typename KeyEqual = equal_to< Key > 28 // typename Hash = hash<Key>(), 29 // typename Predicate = equal_to<Key>, 228 typename KeyEqual = equal_to< Key >, 229 typename HashEntryPolicy = hash_table_stl_map_policy< Key, T, size_t, KeyEqual, Hash > 30 230 > 31 231 class unordered_map 32 : public hash_table< hash_table_entry_stl_map< Key, T, size_t, KeyEqual, Hash > > 232 : public hash_table< 233 HashEntryPolicy, 234 hash_table_no_extra_types_policy, 235 hash_table_prime_rehash_policy, 236 HashEntryPolicy 237 > 33 238 { 34 239 public: 35 typedef hash_table< hash_table_entry_stl_map< Key, T, size_t, KeyEqual, Hash > > base_type; 36 typedef unordered_map< Key, T, Hash, KeyEqual > this_type; 240 typedef hash_table< 241 HashEntryPolicy, 242 hash_table_no_extra_types_policy, 243 hash_table_prime_rehash_policy, 244 HashEntryPolicy 245 > base_type; 37 246 typedef typename base_type::value_type value_type; 38 247 typedef typename base_type::pointer pointer; … … 51 260 typedef KeyEqual key_equal; 52 261 53 unordered_map() : base_type() { } 54 explicit unordered_map( size_type bucket_count ) : base_type( bucket_count ) { } 262 using base_type::base_type; 55 263 56 264 mapped_type& operator[]( const key_type& key ) … … 59 267 } 60 268 269 mapped_type& at( const key_type& key ) 270 { 271 iterator it = base_type::find( key ); 272 NV_ASSERT_ALWAYS( it != base_type::end(), "Key not found in map!" ); 273 return *it; 274 } 275 276 const mapped_type& at( const key_type& key ) const 277 { 278 const_iterator it = base_type::find( key ); 279 NV_ASSERT_ALWAYS( it != base_type::cend(), "Key not found in map!" ); 280 return *it; 281 } 282 283 size_type count( const key_type& key ) const 284 { 285 return base_type::find( key ) == base_type::cend() ? 0 : 1; 286 } 287 288 pair<iterator, iterator> equal_range( const key_type& key ) 289 { 290 iterator it = base_type::find( key ); 291 return pair<iterator, iterator>( it, it == base_type::end() ? it : ++it ); 292 } 293 294 pair<const_iterator, const_iterator> equal_range( const key_type& key ) const 295 { 296 const_iterator it = base_type::find( key ); 297 return pair<const_iterator, const_iterator>( it, it == base_type::cend() ? it : ++it ); 298 } 299 61 300 using base_type::insert; 62 301 302 template < typename M > 303 insert_return_type insert_or_assign( const key_type& k, M&& obj ) 304 { 305 insert_return_type result = base_type::try_insert( k, nv::forward<M>( obj ) ); 306 if ( !result.second ) result.first->second = obj; 307 return result; 308 } 309 310 template < typename M > 311 insert_return_type insert_or_assign( key_type&& k, M&& obj ) 312 { 313 insert_return_type result = base_type::try_insert( nv::forward<key_type>( k ), nv::forward<M>( obj ) ); 314 if ( !result.second ) result.first->second = obj; 315 return result; 316 } 317 63 318 // STL compatibility only, hint unused 64 319 iterator insert( const_iterator, const value_type& value )
Note: See TracChangeset
for help on using the changeset viewer.