BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlc_flathashtable_cpp03.h
Go to the documentation of this file.
1/// @file bdlc_flathashtable_cpp03.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlc_flathashtable_cpp03.h -*-C++-*-
8
9// Automatically generated file. **DO NOT EDIT**
10
11#ifndef INCLUDED_BDLC_FLATHASHTABLE_CPP03
12#define INCLUDED_BDLC_FLATHASHTABLE_CPP03
13
14/// @defgroup bdlc_flathashtable_cpp03 bdlc_flathashtable_cpp03
15/// @brief Provide C++03 implementation for bdlc_flathashtable.h
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlc
19/// @{
20/// @addtogroup bdlc_flathashtable_cpp03
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlc_flathashtable_cpp03-purpose"> Purpose</a>
25/// * <a href="#bdlc_flathashtable_cpp03-classes"> Classes </a>
26/// * <a href="#bdlc_flathashtable_cpp03-description"> Description </a>
27///
28/// # Purpose {#bdlc_flathashtable_cpp03-purpose}
29/// Provide C++03 implementation for bdlc_flathashtable.h
30///
31/// # Classes {#bdlc_flathashtable_cpp03-classes}
32/// See bdlc_flathashtable.h for list of classes
33///
34/// @see bdlc_flathashtable
35///
36/// # Description {#bdlc_flathashtable_cpp03-description}
37/// This component is the C++03 translation of a C++11 component,
38/// generated by the 'sim_cpp11_features.pl' program. If the original header
39/// contains any specially delimited regions of C++11 code, then this generated
40/// file contains the C++03 equivalent, i.e., with variadic templates expanded
41/// and rvalue-references replaced by 'bslmf::MovableRef' objects. The header
42/// code in this file is designed to be '#include'd into the original header
43/// when compiling with a C++03 compiler. If there are no specially delimited
44/// regions of C++11 code, then this header contains no code and is not
45/// '#include'd in the original header.
46///
47/// Generated on Sun Sep 1 06:02:14 2024
48/// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
49/// @}
50/** @} */
51/** @} */
52
53/** @addtogroup bdl
54 * @{
55 */
56/** @addtogroup bdlc
57 * @{
58 */
59/** @addtogroup bdlc_flathashtable_cpp03
60 * @{
61 */
62
63#ifdef COMPILING_BDLC_FLATHASHTABLE_H
64
65
66namespace bdlc {
67
68// FORWARD DECLARATIONS
69struct FlatHashTable_ImplUtil;
70
71template <class ENTRY>
72class FlatHashTable_IteratorImp;
73
74template <class ENTRY>
75bool operator==(const class FlatHashTable_IteratorImp<ENTRY>&,
76 const class FlatHashTable_IteratorImp<ENTRY>&);
77
78 // ===============================
79 // class FlatHashTable_IteratorImp
80 // ===============================
81
82/// This class implements the methods required by `bsl::ForwardIterator` to
83/// provide forward iterators. As such, an instance of this class
84/// represents a position within a flat hash table. This class uses no
85/// features of the `ENTRY` type except for addresses of `ENTRY` objects.
86template <class ENTRY>
87class FlatHashTable_IteratorImp
88{
89 // PRIVATE TYPES
90 typedef FlatHashTable_GroupControl GroupControl;
91
92 // DATA
93 ENTRY *d_entries_p;
94 const bsl::uint8_t *d_controls_p;
95 bsl::size_t d_additionalLength;
96
97 // FRIENDS
98 friend bool operator==<>(const FlatHashTable_IteratorImp&,
100
101 public:
102 // CREATORS
103
104 /// Create a `FlatHashTable_IteratorImp` having the default,
105 /// non-dereferencable value.
107
108 /// Create a `FlatHashTable_IteratorImp` referencing the first element
109 /// of the specified `entries` and `controls`, which have the specified
110 /// `additionalLength` values. The behavior is undefined unless
111 /// `entries` points to at least `1 + additionalLength` entry values and
112 /// `controls` points to at least
113 /// `1 + additionalLength + ControlGroup::k_SIZE` control values.
114 FlatHashTable_IteratorImp(ENTRY *entries,
115 const bsl::uint8_t *controls,
116 bsl::size_t additionalLength);
117
118 /// Create a `FlatHashTable_IteratorImp` having the same value as the
119 /// specified `original`.
121
122 ~FlatHashTable_IteratorImp() = default;
123 // Destroy this object.
124
125 // MANIPULATORS
126
127 /// Assign to this `FlatHashTable_IteratorImp` the value of the
128 /// specified `rhs`.
130
131 /// Advance the `FlatHashTable_IteratorImp` to the next present element
132 /// in the underlying flat hash table. If there is no such element,
133 /// assign this object to `FlatHashTable_InteratorImp()`. The behavior
134 /// is undefined unless this `FlatHashTable_IteratorImp` refers to a
135 /// valid element of the underlying sequence.
136 void operator++();
137
138 // ACCESSORS
139
140 /// Return a reference to the element referred to by this
141 /// `FlatHashTable_IteratorImp`. The behavior is undefined unless this
142 /// `FlatHashTable_IteratorImp() != *this`.
143 ENTRY& operator*() const;
144};
145
146// FREE OPERATORS
147
148/// Return true if the specified `a` and `b` are equal. Two
149/// `FlatHashTable_IteratorImp` objects are equal if they both refer to the
150/// same element of the underlying flat hash table, or are both not
151/// dereferenceable. The behavior is undefined unless `a` and `b` refer to
152/// the same `FlatHashTable`.
153template <class ENTRY>
154bool operator==(const FlatHashTable_IteratorImp<ENTRY>& a,
155 const FlatHashTable_IteratorImp<ENTRY>& b);
156
157 // ===================
158 // class FlatHashTable
159 // ===================
160
161/// This class template provides a flat hash table implementation useful for
162/// implementing a flat hash set and flat hash map.
163template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
164class FlatHashTable
165{
166 // PRIVATE TYPES
167 typedef FlatHashTable_GroupControl GroupControl;
168 typedef FlatHashTable_ImplUtil ImplUtil;
169 typedef FlatHashTable_IteratorImp<ENTRY> IteratorImp;
170
171 public:
172 // TYPES
173 typedef KEY key_type;
174 typedef ENTRY entry_type;
175 typedef ENTRY_UTIL entry_util_type;
176 typedef HASH hash_type;
177 typedef EQUAL key_equal_type;
178
179 typedef typename bslstl::ForwardIterator<ENTRY,
180 IteratorImp> iterator;
181 typedef typename bslstl::ForwardIterator<const ENTRY,
182 IteratorImp> const_iterator;
183
184 private:
185 // DATA
186 ENTRY *d_entries_p; // entries of this table
187 bsl::uint8_t *d_controls_p; // control values of this table
188 bsl::size_t d_size; // number of active values
189 bsl::size_t d_capacity; // size of values array
190 int d_groupControlShift; // number of bits to shift hash
191 HASH d_hasher; // hashing functor
192 EQUAL d_equal; // equality functor
193 bslma::Allocator *d_allocator_p; // allocator
194
195 // PRIVATE CLASS METHODS
196
197 /// Return the index of the first available entry indicated by the
198 /// specified `controls` at or after the specified `index`, assuming
199 /// `controls` has the specified `capacity`. The behavior is undefined
200 /// unless `index < capacity` and `controls` has at least `capacity`
201 /// entries.
202 static bsl::size_t findAvailable(bsl::uint8_t *controls,
203 bsl::size_t index,
204 bsl::size_t capacity);
205
206 // PRIVATE MANIPULATORS
207
208 /// Load `true` into the specified `notFound` if there is no entry in
209 /// this table having the specified `key` with the specified
210 /// `hashValue`, and `false` otherwise. Return the index of the entry
211 /// within `d_entries_p` which contains the `key` if such an entry
212 /// exists, otherwise insert an entry with value obtained from
213 /// `ENTRY_UTIL::construct` and return the index of this entry. This
214 /// method rehashes the table if the `key` was not present and the
215 /// addition of an entry would cause the load factor to exceed
216 /// `max_load_factor()`. The behavior is undefined unless
217 /// `hashValue == d_hasher(key)`.
218 bsl::size_t indexOfKey(bool *notFound,
219 const KEY& key,
220 bsl::size_t hashValue);
221
222 /// Change the capacity of this table to the specified `newCapacity`,
223 /// and redistribute all the contained elements into the new sequence of
224 /// entries, according to their hash values. The behavior is undefined
225 /// unless `0 < newCapacity` and `newCapacity` satisfies all class
226 /// invariants.
227 void rehashRaw(bsl::size_t newCapacity);
228
229 // PRIVATE ACCESSORS
230
231 /// Return the index of the entry within `d_entries_p` containing the
232 /// specified `key`, which has the specified `hashValue`, or
233 /// `d_capacity` if the `key` is not present. The behavior is undefined
234 /// unless `hashValue == d_hasher(key)`.
235 bsl::size_t findKey(const KEY& key, bsl::size_t hashValue) const;
236
237 /// Return the minimum capacity that satisfies all class invariants, and
238 /// is at least the specified `minimumCapacity`.
239 bsl::size_t minimumCompliantCapacity(bsl::size_t minimumCapacity) const;
240
241 // NOT IMPLEMENTED
242 FlatHashTable();
243
244 public:
245 // PUBLIC CLASS DATA
246 static const bsl::size_t k_MIN_CAPACITY = 2 * GroupControl::k_SIZE;
247 // min. non-zero capacity
248
249 static const bsl::int8_t k_HASHLET_MASK = 0x7f; // hashlet = hash & MASK
250
251 static const bsl::size_t k_MAX_LOAD_FACTOR_NUMERATOR = 7;
252 // numerator of fraction
253 // that specifies the
254 // maximum load factor
255
256 static const bsl::size_t k_MAX_LOAD_FACTOR_DENOMINATOR = 8;
257 // denominator of
258 // fraction that
259 // specifies the maximum
260 // load factor
261
262 // CREATORS
263
264 /// Create an empty table having at least the specified `capacity`, that
265 /// will use the specified `hash` to generate hash values for the keys
266 /// of the entries contained in this table, and the specified `equal` to
267 /// verify that the keys of the two entries are the same. Optionally
268 /// specify a `basicAllocator` used to supply memory. If
269 /// `basicAllocator` is 0, the currently installed default allocator is
270 /// used. If `0 == capacity`, no memory is allocated and the object is
271 /// defined to be in the "zero-capacity" state.
272 FlatHashTable(bsl::size_t capacity,
273 const HASH& hash,
274 const EQUAL& equal,
275 bslma::Allocator *basicAllocator = 0);
276
277 /// Create a table having the same value, hasher, and key-equality
278 /// comparator as the specified `original`. Optionally specify a
279 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
280 /// the currently installed default allocator is used.
281 FlatHashTable(const FlatHashTable& original,
282 bslma::Allocator *basicAllocator = 0);
283
284 /// Create an table having the same value as the specified `original`
285 /// object by moving (in constant time) the contents of `original` to
286 /// the new table. Use a copy of `original.hash_function()` to generate
287 /// hash values for the keys of the entries contained in this table.
288 /// Use a copy of `original.key_eq()` to verify that two keys are equal.
289 /// The allocator associated with `original` is propagated for use in
290 /// the newly-created table. `original` is left in a (valid)
291 /// unspecified state.
292 explicit FlatHashTable(bslmf::MovableRef<FlatHashTable> original);
293
294 /// Create a table having the same value, hasher, and key-equality
295 /// comparator as the specified `original` object by moving the contents
296 /// of `original` to the new table, and using the specified
297 /// `basicAllocator` to supply memory. Use a copy of
298 /// `original.hash_function()` to generate hash values for the entries
299 /// contained in this table. Use a copy of `original.key_eq()` to
300 /// verify that the keys of two entries are equal. This method requires
301 /// that the (template parameter) type `ENTRY` be `move-insertable` into
302 /// this `FlatHashTable`. If `basicAllocator` is 0, the currently
303 /// installed default allocator is used. If `original` and the newly
304 /// created object have the same allocator then the value of `original`
305 /// becomes unspecified but valid, and no exceptions will be thrown;
306 /// otherwise `original` is unchanged (and an exception may be thrown).
307 FlatHashTable(bslmf::MovableRef<FlatHashTable> original,
308 bslma::Allocator *basicAllocator);
309
310 /// Destroy this object and each of its entries.
312
313 // MANIPULATORS
314
315 /// Assign to this object the value, hasher, and key-equality functor of
316 /// the specified `rhs` object and return a reference offering
317 /// modifiable access to this object.
318 FlatHashTable& operator=(const FlatHashTable& rhs);
319
320 /// Assign to this object the value, hash function, and key-equality
321 /// comparator of the specified `rhs` object and return a reference
322 /// offering modifiable access to this object. The entries of `rhs` are
323 /// moved (in constant time) to this object if the two have the same
324 /// allocator, otherwise entries from `rhs` are moved into this table.
325 /// In either case, `rhs` is left in a valid but unspecified state. If
326 /// an exception is thrown, this object is left in a valid but
327 /// unspecified state.
329
330 /// If an entry with the specified `key` is not already present in this
331 /// table, insert an entry having the value defined by
332 /// `ENTRY_UTIL::construct`; otherwise, this method has no effect.
333 /// Return an iterator referring to the (possibly newly inserted) object
334 /// in this table with the `key`.
335 template <class KEY_TYPE>
336 ENTRY& operator[](BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) key);
337
338 /// Remove all entries from this table. Note that this table will be
339 /// empty after calling this method, but allocated memory may be
340 /// retained for future use. See the `capacity` method.
341 void clear();
342
343 /// Return a pair of iterators providing modifiable access to the
344 /// sequence of objects in this flat hash table having the specified
345 /// `key`, where the first iterator is positioned at the start of the
346 /// sequence, and the second is positioned one past the end of the
347 /// sequence. If this table contains no object having `key`, then the
348 /// two returned iterators will have the same value, `end()`. Note that
349 /// since each key in a flat hash table is unique, the returned range
350 /// contains at most one element.
352
353#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
354// {{{ BEGIN GENERATED CODE
355// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
356#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
357#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
358#endif
359#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A
360#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A BDLC_FLATHASHTABLE_VARIADIC_LIMIT
361#endif
362#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 0
364 );
365#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 0
366
367#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 1
368 template< class ARGS_01>
370 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01);
371#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 1
372
373#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 2
374 template< class ARGS_01,
375 class ARGS_02>
377 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
378 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02);
379#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 2
380
381#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 3
382 template< class ARGS_01,
383 class ARGS_02,
384 class ARGS_03>
386 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
387 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
388 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03);
389#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 3
390
391#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 4
392 template< class ARGS_01,
393 class ARGS_02,
394 class ARGS_03,
395 class ARGS_04>
397 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
398 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
399 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
400 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04);
401#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 4
402
403#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 5
404 template< class ARGS_01,
405 class ARGS_02,
406 class ARGS_03,
407 class ARGS_04,
408 class ARGS_05>
410 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
411 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
412 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
413 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
414 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05);
415#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 5
416
417#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 6
418 template< class ARGS_01,
419 class ARGS_02,
420 class ARGS_03,
421 class ARGS_04,
422 class ARGS_05,
423 class ARGS_06>
425 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
426 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
427 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
428 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
429 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
430 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06);
431#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 6
432
433#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 7
434 template< class ARGS_01,
435 class ARGS_02,
436 class ARGS_03,
437 class ARGS_04,
438 class ARGS_05,
439 class ARGS_06,
440 class ARGS_07>
442 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
443 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
444 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
445 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
446 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
447 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
448 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07);
449#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 7
450
451#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 8
452 template< class ARGS_01,
453 class ARGS_02,
454 class ARGS_03,
455 class ARGS_04,
456 class ARGS_05,
457 class ARGS_06,
458 class ARGS_07,
459 class ARGS_08>
461 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
462 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
463 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
464 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
465 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
466 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
467 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
468 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08);
469#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 8
470
471#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 9
472 template< class ARGS_01,
473 class ARGS_02,
474 class ARGS_03,
475 class ARGS_04,
476 class ARGS_05,
477 class ARGS_06,
478 class ARGS_07,
479 class ARGS_08,
480 class ARGS_09>
482 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
483 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
484 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
485 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
486 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
487 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
488 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
489 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
490 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09);
491#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 9
492
493#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 10
494 template< class ARGS_01,
495 class ARGS_02,
496 class ARGS_03,
497 class ARGS_04,
498 class ARGS_05,
499 class ARGS_06,
500 class ARGS_07,
501 class ARGS_08,
502 class ARGS_09,
503 class ARGS_10>
505 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
506 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
507 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
508 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
509 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
510 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
511 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
512 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
513 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
514 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10);
515#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 10
516
517#else
518// The generated code below is a workaround for the absence of perfect
519// forwarding in some compilers.
520 template< class... ARGS>
523// }}} END GENERATED CODE
524#endif
525
526 /// Remove from this table the object having the specified `key`, if it
527 /// exists, and return 1; otherwise (there is no object with a key equal
528 /// to `key` in this table) return 0 with no other effect. This method
529 /// invalidates all iterators, and references to the removed element.
530 bsl::size_t erase(const KEY& key);
531
532 iterator erase(const_iterator position);
533 /// Remove from this table the object at the specified `position`, and
534 /// return an iterator referring to the element immediately following
535 /// the removed element, or to the past-the-end position if the removed
536 /// element was the last element in the sequence of elements maintained
537 /// by this table. This method invalidates all iterators, and
538 /// references to the removed element. The behavior is undefined unless
539 /// `position` refers to an object in this table.
540 iterator erase(iterator position);
541
542 /// Remove from this table the objects starting at the specified `first`
543 /// position up to, but not including, the specified `last` position,
544 /// and return `last`. This method invalidates all iterators, and
545 /// references to the removed element. The behavior is undefined unless
546 /// `first` and `last` either refer to elements in this table or are the
547 /// `end` iterator, and the `first` position is at or before the `last`
548 /// position in the iteration sequence provided by this container.
550
551 /// Return an iterator providing modifiable access to the object in this
552 /// flat hash table with a key equal to the specified `key`, if such an
553 /// entry exists, and `end()` otherwise.
554 iterator find(const KEY& key);
555
556#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
557 template <class ENTRY_TYPE>
559 BSLS_COMPILERFEATURES_FORWARD_REF(ENTRY_TYPE) entry)
560#else
561 /// Insert the specified `entry` into this table if the key of the
562 /// `entry` does not already exist in this table; otherwise, this method
563 /// has no effect. Return a `pair` whose `first` member is an iterator
564 /// referring to the (possibly newly inserted) object in this table
565 /// whose key is the equal to that of the object to be inserted, and
566 /// whose `second` member is `true` if a new entry was inserted, and
567 /// `false` if a entry having an equal key was already present. Bitwise
568 /// movable types that are not bitwise copyable will be copied (to avoid
569 /// confusion with regard to calling the `entry` destructor after this
570 /// call).
571 template <class ENTRY_TYPE>
575#endif
576 {
577 // Note that some compilers require functions declared with 'enable_if'
578 // to be defined inline.
579
580 bool notFound;
581 bsl::size_t hashValue = d_hasher(ENTRY_UTIL::key(entry));
582 bsl::size_t index = indexOfKey(&notFound,
583 ENTRY_UTIL::key(entry),
584 hashValue);
585
586 if (notFound) {
587 ENTRY_UTIL::construct(
588 d_entries_p + index,
589 d_allocator_p,
590 BSLS_COMPILERFEATURES_FORWARD(ENTRY_TYPE, entry));
591
592 d_controls_p[index] = static_cast<bsl::uint8_t>(
593 hashValue & k_HASHLET_MASK);
594
595 ++d_size;
596 }
597
598 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
599 d_controls_p + index,
600 d_capacity - index - 1),
601 notFound);
602 }
603
604 /// Create an object for each iterator in the range starting at the
605 /// specified `first` iterator and ending immediately before the
606 /// specified `last` iterator, by converting from the object referred to
607 /// by each iterator. Insert into this table each such object whose key
608 /// is not already contained. The (template parameter) type
609 /// `INPUT_ITERATOR` shall meet the requirements of an input iterator
610 /// defined in the C++11 standard [24.2.3] providing access to values of
611 /// a type convertible to `ENTRY`. The behavior is undefined unless
612 /// `first` and `last` refer to a sequence of valid values where `first`
613 /// is at a position at or before `last`.
614 template <class INPUT_ITERATOR>
615 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
616
617 /// Change the capacity of this table to at least the specified
618 /// `minimumCapacity`, and redistribute all the contained elements into
619 /// a new sequence of entries, according to their hash values. If
620 /// `0 == minimumCapacity` and `0 == size()`, the table is returned to
621 /// the zero-capacity state. On return, `load_factor()` is less than or
622 /// equal to `max_load_factor()` and all iterators, pointers, and
623 /// references to elements of this `FlatHashTable` are invalidated.
624 void rehash(bsl::size_t minimumCapacity);
625
626 /// Change the capacity of this table to at least a capacity that can
627 /// accommodate the specified `numEntries` (accounting for the load
628 /// factor invariant), and redistribute all the contained elements into
629 /// a new sequence of entries, according to their hash values. If
630 /// `0 == numEntries` and `0 == size()`, the table is returned to the
631 /// zero-capacity state. After this call, `load_factor()` will be less
632 /// than or equal to `max_load_factor()`. Note that this method is
633 /// effectively equivalent to:
634 /// @code
635 /// rehash(bsl::ceil(numEntries / max_load_factor()))
636 /// @endcode
637 void reserve(bsl::size_t numEntries);
638
639 /// Remove all entries from this table and release all memory from this
640 /// table, returning the table to the zero-capacity state.
641 void reset();
642
643#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
644// {{{ BEGIN GENERATED CODE
645// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
646#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
647#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
648#endif
649#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B
650#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B BDLC_FLATHASHTABLE_VARIADIC_LIMIT
651#endif
652#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 0
654#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 0
655
656#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 1
657 template< class ARGS_01>
659 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01);
660#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 1
661
662#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 2
663 template< class ARGS_01,
664 class ARGS_02>
666 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
667 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02);
668#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 2
669
670#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 3
671 template< class ARGS_01,
672 class ARGS_02,
673 class ARGS_03>
675 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
676 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
677 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03);
678#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 3
679
680#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 4
681 template< class ARGS_01,
682 class ARGS_02,
683 class ARGS_03,
684 class ARGS_04>
686 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
687 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
688 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
689 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04);
690#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 4
691
692#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 5
693 template< class ARGS_01,
694 class ARGS_02,
695 class ARGS_03,
696 class ARGS_04,
697 class ARGS_05>
699 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
700 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
701 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
702 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
703 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05);
704#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 5
705
706#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 6
707 template< class ARGS_01,
708 class ARGS_02,
709 class ARGS_03,
710 class ARGS_04,
711 class ARGS_05,
712 class ARGS_06>
714 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
715 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
716 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
717 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
718 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
719 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06);
720#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 6
721
722#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 7
723 template< class ARGS_01,
724 class ARGS_02,
725 class ARGS_03,
726 class ARGS_04,
727 class ARGS_05,
728 class ARGS_06,
729 class ARGS_07>
731 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
732 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
733 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
734 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
735 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
736 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
737 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07);
738#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 7
739
740#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 8
741 template< class ARGS_01,
742 class ARGS_02,
743 class ARGS_03,
744 class ARGS_04,
745 class ARGS_05,
746 class ARGS_06,
747 class ARGS_07,
748 class ARGS_08>
750 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
751 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
752 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
753 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
754 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
755 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
756 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
757 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08);
758#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 8
759
760#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 9
761 template< class ARGS_01,
762 class ARGS_02,
763 class ARGS_03,
764 class ARGS_04,
765 class ARGS_05,
766 class ARGS_06,
767 class ARGS_07,
768 class ARGS_08,
769 class ARGS_09>
771 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
772 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
773 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
774 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
775 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
776 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
777 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
778 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
779 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09);
780#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 9
781
782#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 10
783 template< class ARGS_01,
784 class ARGS_02,
785 class ARGS_03,
786 class ARGS_04,
787 class ARGS_05,
788 class ARGS_06,
789 class ARGS_07,
790 class ARGS_08,
791 class ARGS_09,
792 class ARGS_10>
794 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
795 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
796 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
797 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
798 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
799 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
800 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
801 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
802 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
803 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10);
804#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 10
805
806
807#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 0
809 BloombergLP::bslmf::MovableRef<KEY> key);
810#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 0
811
812#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 1
813 template <class ARGS_01>
815 BloombergLP::bslmf::MovableRef<KEY> key,
816 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01);
817#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 1
818
819#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 2
820 template <class ARGS_01,
821 class ARGS_02>
823 BloombergLP::bslmf::MovableRef<KEY> key,
824 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
825 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02);
826#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 2
827
828#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 3
829 template <class ARGS_01,
830 class ARGS_02,
831 class ARGS_03>
833 BloombergLP::bslmf::MovableRef<KEY> key,
834 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
835 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
836 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03);
837#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 3
838
839#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 4
840 template <class ARGS_01,
841 class ARGS_02,
842 class ARGS_03,
843 class ARGS_04>
845 BloombergLP::bslmf::MovableRef<KEY> key,
846 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
847 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
848 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
849 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04);
850#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 4
851
852#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 5
853 template <class ARGS_01,
854 class ARGS_02,
855 class ARGS_03,
856 class ARGS_04,
857 class ARGS_05>
859 BloombergLP::bslmf::MovableRef<KEY> key,
860 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
861 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
862 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
863 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
864 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05);
865#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 5
866
867#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 6
868 template <class ARGS_01,
869 class ARGS_02,
870 class ARGS_03,
871 class ARGS_04,
872 class ARGS_05,
873 class ARGS_06>
875 BloombergLP::bslmf::MovableRef<KEY> key,
876 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
877 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
878 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
879 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
880 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
881 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06);
882#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 6
883
884#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 7
885 template <class ARGS_01,
886 class ARGS_02,
887 class ARGS_03,
888 class ARGS_04,
889 class ARGS_05,
890 class ARGS_06,
891 class ARGS_07>
893 BloombergLP::bslmf::MovableRef<KEY> key,
894 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
895 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
896 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
897 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
898 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
899 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
900 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07);
901#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 7
902
903#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 8
904 template <class ARGS_01,
905 class ARGS_02,
906 class ARGS_03,
907 class ARGS_04,
908 class ARGS_05,
909 class ARGS_06,
910 class ARGS_07,
911 class ARGS_08>
913 BloombergLP::bslmf::MovableRef<KEY> key,
914 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
915 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
916 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
917 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
918 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
919 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
920 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
921 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08);
922#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 8
923
924#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 9
925 template <class ARGS_01,
926 class ARGS_02,
927 class ARGS_03,
928 class ARGS_04,
929 class ARGS_05,
930 class ARGS_06,
931 class ARGS_07,
932 class ARGS_08,
933 class ARGS_09>
935 BloombergLP::bslmf::MovableRef<KEY> key,
936 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
937 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
938 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
939 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
940 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
941 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
942 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
943 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
944 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09);
945#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 9
946
947#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 10
948 template <class ARGS_01,
949 class ARGS_02,
950 class ARGS_03,
951 class ARGS_04,
952 class ARGS_05,
953 class ARGS_06,
954 class ARGS_07,
955 class ARGS_08,
956 class ARGS_09,
957 class ARGS_10>
959 BloombergLP::bslmf::MovableRef<KEY> key,
960 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
961 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
962 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
963 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
964 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
965 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
966 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
967 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
968 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
969 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10);
970#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_B >= 10
971
972#else
973// The generated code below is a workaround for the absence of perfect
974// forwarding in some compilers.
975 template< class... ARGS>
978
979 template <class... ARGS>
981 BloombergLP::bslmf::MovableRef<KEY> key,
983// }}} END GENERATED CODE
984#endif
985
986 // Iterators
987
988 /// Return an iterator representing the beginning of the sequence of
989 /// entries held by this container.
990 iterator begin();
991
992 /// Return an iterator representing one past the end of the sequence of
993 /// entries held by this container.
994 iterator end();
995
996 // Aspects
997
998 /// Efficiently exchange the value of this table with the value of the
999 /// specified `other` table. This method provides the no-throw
1000 /// exception-safety guarantee. The behavior is undefined unless this
1001 /// array was created with the same allocator as `other`.
1002 void swap(FlatHashTable& other);
1003
1004 // ACCESSORS
1005
1006 /// Return the number of elements this table could hold if the load
1007 /// factor were 1.
1008 bsl::size_t capacity() const;
1009
1010 /// Return `true` if this table contains an entry having the specified
1011 /// `key`, and `false` otherwise.
1012 bool contains(const KEY& key) const;
1013
1014 /// Return the address of the first element of the underlying array of
1015 /// control values in this table, or 0 if this table is in the
1016 /// zero-capacity state. An element of this array has the value
1017 /// `FlatHashTable_GroupControl::k_EMPTY`,
1018 /// `FlatHashTable_GroupControl::k_ERASED`, or a seven bit hashlet value
1019 /// for the in-use position (the highest-order bit is unset).
1020 const bsl::uint8_t *controls() const;
1021
1022 /// Return the number of objects contained within this table having the
1023 /// specified `key`. Note that since a table maintains unique keys, the
1024 /// returned value will be either 0 or 1.
1025 bsl::size_t count(const KEY& key) const;
1026
1027 /// Return `true` if this table contains no entries, and `false`
1028 /// otherwise.
1029 bool empty() const;
1030
1031 /// Return the address of the first element of the underlying array of
1032 /// entries in this table, or 0 if this table is in the zero-capacity
1033 /// state. The behavior is undefined unless the address is verified
1034 /// in-use through use of the `controls` array before dereferencing an
1035 /// entry in this array.
1036 const ENTRY *entries() const;
1037
1038 /// Return a pair of iterators providing non-modifiable access to the
1039 /// sequence of objects in this table having the specified `key`, where
1040 /// the first iterator is positioned at the start of the sequence, and
1041 /// the second is positioned one past the end of the sequence. If this
1042 /// table contains no objects having `key`, then the two returned
1043 /// iterators will have the same value, `end()`. Note that since a
1044 /// table maintains unique keys, the range will contain at most one
1045 /// entry.
1047 const KEY& key) const;
1048
1049 /// Return an iterator representing the position of the entry in this
1050 /// flat hash table having the specified `key`, or `end()` if no such
1051 /// entry exists in this table.
1052 const_iterator find(const KEY& key) const;
1053
1054 /// Return (a copy of) the unary hash functor used by this flat hash
1055 /// table to generate a hash value (of type `bsl::size_t) for a `KEY'
1056 /// object.
1057 HASH hash_function() const;
1058
1059 /// Return (a copy of) the binary key-equality functor used by this flat
1060 /// hash table that returns `true` if two `KEY` objects are equal, and
1061 /// `false` otherwise.
1062 EQUAL key_eq() const;
1063
1064 /// Return the current ratio between the number of elements in this
1065 /// table and its capacity.
1066 float load_factor() const;
1067
1068 /// Return the maximum load factor allowed for this table. Note that if
1069 /// an insert operation would cause the load factor to exceed the
1070 /// `max_load_factor`, that same insert operation will increase the
1071 /// capacity and rehash the entries of the container (see `insert` and
1072 /// `rehash`). Note that the value returned by `max_load_factor` is
1073 /// implementation dependent and cannot be changed by the user.
1074 float max_load_factor() const;
1075
1076 /// Return the number of entries in this table.
1077 bsl::size_t size() const;
1078
1079 // Iterators
1080
1081 const_iterator begin() const;
1082
1083 /// Return an iterator representing the beginning of the sequence of
1084 /// entries held by this container.
1085 const_iterator cbegin() const;
1086
1087 const_iterator cend() const;
1088
1089 /// Return an iterator representing one past the end of the sequence of
1090 /// entries held by this container.
1091 const_iterator end() const;
1092
1093 // Aspects
1094
1095 /// Return the allocator used by this hash table to supply memory.
1096 bslma::Allocator *allocator() const;
1097};
1098
1099// FREE OPERATORS
1100
1101/// Return `true` if the specified `lhs` and `rhs` objects have the same
1102/// value, and `false` otherwise. Two `FlatHashTable` objects have the same
1103/// value if they have the same number of entries, and for each entry that
1104/// is contained in `lhs` there is a entry contained in `rhs` having the
1105/// same value. Note that this method requires the (template parameter)
1106/// type `ENTRY` to be equality-comparable.
1107template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1108bool operator==(const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& lhs,
1109 const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& rhs);
1110
1111/// Return `true` if the specified `lhs` and `rhs` objects do not have the
1112/// same value, and `false` otherwise. Two `FlatHashTable` objects do not
1113/// have the same value if they do not have the same number of entries, or
1114/// that for some entry contained in `lhs` there is not a entry in `rhs`
1115/// having the same value. Note that this method requires the (template
1116/// parameter) type `ENTRY` to be equality-comparable.
1117template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1118bool operator!=(const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& lhs,
1119 const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& rhs);
1120
1121// FREE FUNCTIONS
1122
1123/// Exchange the values of the specified `a` and `b` objects. This function
1124/// provides the no-throw exception-safety guarantee if the two objects were
1125/// created with the same allocator and the basic guarantee otherwise.
1126template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1127void swap(FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& a,
1128 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& b);
1129
1130 // =============================
1131 // struct FlatHashTable_ImplUtil
1132 // =============================
1133
1134/// This component-private, utility `struct` provides a namespace for a
1135/// suite of operations used in the implementation of the `FlatHashTable`
1136/// class template.
1137struct FlatHashTable_ImplUtil {
1138
1139 private:
1140 // PRIVATE TYPES
1141 typedef FlatHashTable_GroupControl GroupControl;
1142
1143 /// This component-private, mechanism class template provides a proctor
1144 /// that, unless its `release` method has been previously invoked, on
1145 /// destruction automatically destroys the populated `ENTRY_TYPE`
1146 /// elements of an `ENTRY_TYPE` array supplied on construction as
1147 /// indicated by a "control" byte array supplied on construction.
1148 template <class ENTRY_TYPE>
1149 class DestroyEntryArrayProctor;
1150
1151 // PRIVATE CLASS METHODS
1152
1153 /// Copy the specified range `[firstSourceControl, lastSourceControl)`
1154 /// to the array specified by `firstDestinationControl`, and copy each
1155 /// element in the specified range `[firstSourceEntry, lastSourceEntry)`
1156 /// at the same index as each byte in the range '[firstSourceControl,
1157 /// lastSourceControl)' that has its most-significant bit unset, to the
1158 /// corresponding location in the contiguous storage for `ENTRY_TYPE`
1159 /// objects specified by `firstDestinationEntry`. Use the specified
1160 /// `entryAllocator` as the object allocator for each newly-constructed
1161 /// `ENTRY_TYPE` object if `ENTRY_TYPE` is allocator-aware. If
1162 /// `entryAllocator` is 0, the currently-installed default allocator is
1163 /// used. No exception is thrown if the specified `ENTRY_TYPE` is
1164 /// nothrow-copyable, otherwise an exception may be thrown. The
1165 /// behavior is undefined unless
1166 /// `bslmf::IsBitwiseCopyable<ENTRY_TYPE>::value` is equal to the
1167 /// `value` member of the type of the specified `tag`,
1168 /// `firstDestinationEntry` is a pointer to the first byte of
1169 /// uninitialized and correctly aligned storage for at least
1170 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` `ENTRY_TYPE`
1171 /// objects, `firstDestinationControl` is a pointer to the first byte of
1172 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` bytes of
1173 /// uninitialized storage, the range '[firstSourceEntry,
1174 /// lastSourceEntry)' denotes a contiguous array of storage for
1175 /// optionally-constructed `ENTRY_TYPE` objects, the range
1176 /// `[firstSourceControl, lastSourceControl)` denotes a contiguous array
1177 /// of `bsl::uint8_t` objects, an `ENTRY_TYPE` object exists at the same
1178 /// index in the `[firstSourceEntry, lastSourceEntry)` storage range as
1179 /// each byte in the range `[firstControlEntry, lastControlEntry)` that
1180 /// has its most significant bit unset, and
1181 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` is equal to
1182 /// `bsl::distance(firstSourceControl, lastSourceControl)`.
1183 template <class ENTRY_TYPE>
1184 static void copyEntryAndControlArrays(
1185 ENTRY_TYPE *firstDestinationEntry,
1186 bsl::uint8_t *firstDestinationControl,
1187 const ENTRY_TYPE *firstSourceEntry,
1188 const ENTRY_TYPE *lastSourceEntry,
1189 const bsl::uint8_t *firstSourceControl,
1190 const bsl::uint8_t *lastSourceControl,
1191 bslma::Allocator *entryAllocator,
1192 bsl::false_type bitwiseCopyable);
1193 template <class ENTRY_TYPE>
1194 static void copyEntryAndControlArrays(
1195 ENTRY_TYPE *firstDestinationEntry,
1196 bsl::uint8_t *firstDestinationControl,
1197 const ENTRY_TYPE *firstSourceEntry,
1198 const ENTRY_TYPE *lastSourceEntry,
1199 const bsl::uint8_t *firstSourceControl,
1200 const bsl::uint8_t *lastSourceControl,
1201 bslma::Allocator *entryAllocator,
1202 bsl::true_type bitwiseCopyable);
1203
1204
1205 /// Destroy each entry object in the storage specified by the range
1206 /// `[firstEntry, lastEntry)` if the most-significant bit is unset in
1207 /// the corresponding element in the specified range
1208 /// `[firstControl, lastControl)` (i.e., the most-significant bit of the
1209 /// element in the "control" array that has the same index as the
1210 /// element in the "entry" array is unset). No exception is thrown.
1211 /// The behavior is undefined unless
1212 /// `bslmf::IsTriviallyDestructible<ENTRY_TYPE>::value` is equal to the
1213 /// `value` member of the type of the specified `tag`, the range
1214 /// `[firstEntry, lastEntry)` denotes a contiguous array of storage for
1215 /// optionally-constructed `ENTRY_TYPE` objects, the range
1216 /// `[firstControl, lastControl)` denotes a contiguous array of
1217 /// `bsl::uint8_t` objects, the two arrays have the same number of
1218 /// elements, and an `ENTRY_TYPE` object exists at the same index in the
1219 /// `[firstEntry, lastEntry)` storage range for each element in the
1220 /// `[firstControl, lastControl)` range that has its first bit unset.
1221 template <class ENTRY_TYPE>
1222 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
1223 ENTRY_TYPE *lastEntry,
1224 const bsl::uint8_t *firstControl,
1225 const bsl::uint8_t *lastControl,
1226 bsl::false_type triviallyDestructible);
1227 template <class ENTRY_TYPE>
1228 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
1229 ENTRY_TYPE *lastEntry,
1230 const bsl::uint8_t *firstControl,
1231 const bsl::uint8_t *lastControl,
1232 bsl::true_type triviallyDestructible);
1233
1234 public:
1235 // CLASS METHODS
1236
1237 /// Copy the specified range `[firstSourceControl, lastSourceControl)`
1238 /// to the array specified by `firstDestinationControl`, and copy each
1239 /// element in the specified range `[firstSourceEntry, lastSourceEntry)`
1240 /// at the same index as each byte in the range '[firstSourceControl,
1241 /// lastSourceControl)' that has its most-significant bit unset, to the
1242 /// corresponding location in the contiguous storage for `ENTRY_TYPE`
1243 /// objects specified by `firstDestinationEntry`. Use the specified
1244 /// `entryAllocator` as the object allocator for each newly-constructed
1245 /// `ENTRY_TYPE` object if `ENTRY_TYPE` is allocator-aware. If
1246 /// `entryAllocator` is 0, the currently-installed default allocator is
1247 /// used. No exception is thrown if the specified `ENTRY_TYPE` is
1248 /// nothrow-copyable, otherwise an exception may be thrown. The
1249 /// behavior is undefined unless `firstDestinationEntry` is a pointer to
1250 /// the first byte of uninitialized and correctly aligned storage for at
1251 /// least `bsl::distance(firstSourceEntry, lastSourceEntry)`
1252 /// `ENTRY_TYPE` objects, `firstDestinationControl` is a pointer to the
1253 /// first byte of `bsl::distance(firstSourceEntry, lastSourceEntry)`
1254 /// bytes of uninitialized storage, the range '[firstSourceEntry,
1255 /// lastSourceEntry)' denotes a contiguous array of storage for
1256 /// optionally-constructed `ENTRY_TYPE` objects, the range
1257 /// `[firstSourceControl, lastSourceControl)` denotes a contiguous array
1258 /// of `bsl::uint8_t` objects, an `ENTRY_TYPE` object exists at the same
1259 /// index in the `[firstSourceEntry, lastSourceEntry)` storage range as
1260 /// each byte in the range `[firstControlEntry, lastControlEntry)` that
1261 /// has its most significant bit unset, and
1262 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` is equal to
1263 /// `bsl::distance(firstSourceControl, lastSourceControl)`.
1264 template <class ENTRY_TYPE>
1265 static void
1266 copyEntryAndControlArrays(ENTRY_TYPE *firstDestinationEntry,
1267 bsl::uint8_t *firstDestinationControl,
1268 const ENTRY_TYPE *firstSourceEntry,
1269 const ENTRY_TYPE *lastSourceEntry,
1270 const bsl::uint8_t *firstSourceControl,
1271 const bsl::uint8_t *lastSourceControl,
1272 bslma::Allocator *entryAllocator);
1273
1274 /// Destroy each entry object in the storage specified by the range
1275 /// `[firstEntry, lastEntry)` if the most-significant bit is unset in
1276 /// the corresponding element in the specified range '[firstControl,
1277 /// lastControl)' (i.e., the most-significant bit of the element in the
1278 /// "control" array that has the same index as the element in the
1279 /// "entry" array is unset). No exception is thrown. The behavior is
1280 /// undefined unless the range `[firstEntry, lastEntry)` denotes a
1281 /// contiguous array of storage for optionally-constructed `ENTRY_TYPE`
1282 /// objects, the range `[firstControl, lastControl)` denotes a
1283 /// contiguous array of `bsl::uint8_t` objects, the two arrays have the
1284 /// same number of elements, and an `ENTRY_TYPE` object exists at the
1285 /// same index in the `[firstEntry, lastEntry)` storage range for each
1286 /// element in the `[firstControl, lastControl)` range that has its
1287 /// first bit unset.
1288 template <class ENTRY_TYPE>
1289 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
1290 ENTRY_TYPE *lastEntry,
1291 const bsl::uint8_t *firstControl,
1292 const bsl::uint8_t *lastControl);
1293};
1294
1295 // ======================================================
1296 // class FlatHashTable_ImplUtil::DestroyEntryArrayProctor
1297 // ======================================================
1298
1299/// This component-private, mechanism class template provides a proctor
1300/// that, unless its `release` method has been previously invoked, on
1301/// destruction automatically destroys the populated `ENTRY_TYPE` elements
1302/// of an `ENTRY_TYPE` array supplied on construction as indicated by a
1303/// "control" byte array supplied on construction.
1304template <class ENTRY_TYPE>
1305class FlatHashTable_ImplUtil::DestroyEntryArrayProctor {
1306
1307 // PRIVATE TYPES
1308 typedef FlatHashTable_GroupControl GroupControl;
1309 typedef FlatHashTable_ImplUtil ImplUtil;
1310
1311 // DATA
1312
1313 // pointer to first element of entry array
1314 ENTRY_TYPE *d_firstEntry_p;
1315
1316 // pointer to one-past-the-end of entry array
1317 ENTRY_TYPE *d_lastEntry_p;
1318
1319 // pointer to first element of control array
1320 const bsl::uint8_t *d_firstControl_p;
1321
1322 // pointer to one-past-the-end of control array
1323 const bsl::uint8_t *d_lastControl_p;
1324
1325 // NOT IMPLEMENTED
1326 DestroyEntryArrayProctor(const DestroyEntryArrayProctor&);
1327 DestroyEntryArrayProctor& operator=(const DestroyEntryArrayProctor&);
1328
1329 public:
1330 // CREATORS
1331
1332 /// Create a new `DestroyEntryArrayProctor` object for the contiguous
1333 /// `ENTRY_TYPE` storage delimited by the range specified by
1334 /// `[firstEntry, lastEntry)` controlled by the bytes in the range
1335 /// specified by `[firstControl, lastControl)`. The behavior is
1336 /// undefined unless 'bsl::distance(firstEntry, lastEntry) ==
1337 /// bsl::distance(`firstControl, lastControl)`. Note that these ranges
1338 /// may be valid sub-ranges (or "views") of larger arrays, and these
1339 /// sub-ranges can be grown or shrunk by `moveEnd`.
1340 DestroyEntryArrayProctor(ENTRY_TYPE *firstEntry,
1341 ENTRY_TYPE *lastEntry,
1342 const bsl::uint8_t *firstControl,
1343 const bsl::uint8_t *lastControl);
1344
1345 /// Destroy this object and each object in the entry storage array held
1346 /// by this object where the most-significant bit of the corresponding
1347 /// element in the control array held by this object is unset.
1348 ~DestroyEntryArrayProctor();
1349
1350 // MANIPULATORS
1351
1352 /// Move the end of the entry and control ranges held by this object by
1353 /// the specified `offset`.
1354 void moveEnd(bsl::ptrdiff_t offset);
1355
1356 /// Release the entry and control ranges held by this object from
1357 /// management by this object, and set this object's held entry and
1358 /// control arrays to the corresponding empty arrays. If the entry and
1359 /// control arrays held by this object are empty, this method has no
1360 /// effect.
1361 void release();
1362};
1363
1364// ============================================================================
1365// INLINE DEFINITIONS
1366// ============================================================================
1367
1368 // -------------------------------
1369 // class FlatHashTable_IteratorImp
1370 // -------------------------------
1371
1372// CREATORS
1373template <class ENTRY>
1374inline
1376: d_entries_p(0)
1377, d_controls_p(0)
1378, d_additionalLength(0)
1379{
1380}
1381
1382template <class ENTRY>
1383inline
1384FlatHashTable_IteratorImp<ENTRY>::FlatHashTable_IteratorImp(
1385 ENTRY *entries,
1386 const bsl::uint8_t *controls,
1387 bsl::size_t additionalLength)
1388: d_entries_p(entries)
1389, d_controls_p(controls)
1390, d_additionalLength(additionalLength)
1391{
1392}
1393
1394template <class ENTRY>
1395inline
1396FlatHashTable_IteratorImp<ENTRY>::FlatHashTable_IteratorImp(
1397 const FlatHashTable_IteratorImp& original)
1398: d_entries_p(original.d_entries_p)
1399, d_controls_p(original.d_controls_p)
1400, d_additionalLength(original.d_additionalLength)
1401{
1402}
1403
1404// MANIPULATORS
1405template <class ENTRY>
1406inline
1407FlatHashTable_IteratorImp<ENTRY>& FlatHashTable_IteratorImp<ENTRY>::operator=(
1408 const FlatHashTable_IteratorImp& rhs)
1409{
1410 d_entries_p = rhs.d_entries_p;
1411 d_controls_p = rhs.d_controls_p;
1412 d_additionalLength = rhs.d_additionalLength;
1413
1414 return *this;
1415}
1416
1417template <class ENTRY>
1418inline
1419void FlatHashTable_IteratorImp<ENTRY>::operator++()
1420{
1421 BSLS_ASSERT_SAFE(d_entries_p);
1422 BSLS_ASSERT_SAFE(d_controls_p);
1423
1424 while (d_additionalLength) {
1425 ++d_entries_p;
1426 ++d_controls_p;
1427 --d_additionalLength;
1428 if (0 == (*d_controls_p & 0x80)) {
1429 return; // RETURN
1430 }
1431 }
1432
1433 d_entries_p = 0;
1434 d_controls_p = 0;
1435}
1436
1437// ACCESSORS
1438template <class ENTRY>
1439inline
1440ENTRY& FlatHashTable_IteratorImp<ENTRY>::operator*() const
1441{
1442 BSLS_ASSERT_SAFE(d_entries_p);
1443 BSLS_ASSERT_SAFE(d_controls_p);
1444
1445 return *d_entries_p;
1446}
1447
1448} // close package namespace
1449
1450// FREE OPERATORS
1451template <class ENTRY>
1452inline
1453bool bdlc::operator==(const FlatHashTable_IteratorImp<ENTRY>& a,
1454 const FlatHashTable_IteratorImp<ENTRY>& b)
1455{
1456 return a.d_entries_p == b.d_entries_p
1457 && a.d_controls_p == b.d_controls_p
1458 && a.d_additionalLength == b.d_additionalLength;
1459}
1460
1461namespace bdlc {
1462
1463 // -------------------
1464 // class FlatHashTable
1465 // -------------------
1466
1467// PRIVATE CLASS METHODS
1468template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1469bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::findAvailable(
1470 bsl::uint8_t *controls,
1471 bsl::size_t index,
1472 bsl::size_t capacity)
1473{
1474 BSLS_ASSERT_SAFE(index < capacity);
1475
1476 for (bsl::size_t i = 0; i < capacity; i += GroupControl::k_SIZE) {
1477 bsl::uint8_t *controlStart = controls + index;
1478
1479 GroupControl groupControl(controlStart);
1480 bsl::uint32_t candidates = groupControl.available();
1481
1482 if (candidates) {
1483 return index
1484 + bdlb::BitUtil::numTrailingUnsetBits(candidates); // RETURN
1485 }
1486
1487 index = (index + GroupControl::k_SIZE) & (capacity - 1);
1488 }
1489
1490 BSLS_ASSERT_OPT(false && "execution should never reach this location");
1491 return capacity;
1492}
1493
1494// PRIVATE MANIPULATORS
1495template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1496bsl::size_t FlatHashTable<KEY,
1497 ENTRY,
1498 ENTRY_UTIL,
1499 HASH,
1500 EQUAL>::indexOfKey(bool *notFound,
1501 const KEY& key,
1502 bsl::size_t hashValue)
1503{
1504 BSLS_ASSERT_SAFE(hashValue == d_hasher(key));
1505
1506 bsl::size_t index = findKey(key, hashValue);
1507
1508 if (index == d_capacity) {
1509 *notFound = true;
1510
1511 if (d_size >= k_MAX_LOAD_FACTOR_NUMERATOR
1512 * (d_capacity / k_MAX_LOAD_FACTOR_DENOMINATOR)) {
1513 rehashRaw(d_capacity > 0 ? 2 * d_capacity : k_MIN_CAPACITY);
1514 }
1515
1516 index = (hashValue >> d_groupControlShift) * GroupControl::k_SIZE;
1517 index = findAvailable(d_controls_p, index, d_capacity);
1518 }
1519 else {
1520 *notFound = false;
1521 }
1522
1523 return index;
1524}
1525
1526template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1527void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::rehashRaw(
1528 bsl::size_t newCapacity)
1529{
1530 BSLS_ASSERT_SAFE( 0 < newCapacity);
1531 BSLS_ASSERT_SAFE(newCapacity == minimumCompliantCapacity(newCapacity));
1532
1533 FlatHashTable tmp(newCapacity,
1534 d_hasher,
1535 d_equal,
1536 d_allocator_p);
1537
1538 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
1539 bsl::uint8_t *controlStart = d_controls_p + i;
1540 ENTRY *entryStart = d_entries_p + i;
1541
1542 GroupControl groupControl(controlStart);
1543 bsl::uint32_t candidates = groupControl.inUse();
1544 while (candidates) {
1545 int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
1546 ENTRY *entry = entryStart + offset;
1547
1548 // create a destructor proctor for the element to be moved
1549 bslma::DestructorProctor<ENTRY> proctor(entry);
1550
1551 // perform book-keeping for the destruction
1552 *(controlStart + offset) = GroupControl::k_ERASED;
1553 --d_size;
1554
1555 // place the element in the new container
1556 bsl::size_t hashValue = tmp.d_hasher(ENTRY_UTIL::key(*entry));
1557 bsl::size_t index = (hashValue >> tmp.d_groupControlShift)
1558 * GroupControl::k_SIZE;
1559
1560 index = findAvailable(tmp.d_controls_p, index, tmp.d_capacity);
1561
1562 bslma::ConstructionUtil::destructiveMove(tmp.d_entries_p + index,
1563 tmp.d_allocator_p,
1564 entry);
1565
1566 // release destructor proctor
1567 proctor.release();
1568
1569 tmp.d_controls_p[index] = static_cast<bsl::uint8_t>(
1570 hashValue & k_HASHLET_MASK);
1571
1572 ++tmp.d_size;
1573
1574 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
1575 }
1576 }
1577
1578 d_allocator_p->deallocate(d_entries_p);
1579 d_allocator_p->deallocate(d_controls_p);
1580
1581 d_entries_p = 0;
1582 d_controls_p = 0;
1583 d_capacity = 0;
1584 d_groupControlShift = 0;
1585
1586 bslalg::SwapUtil::swap(&d_entries_p, &tmp.d_entries_p);
1587 bslalg::SwapUtil::swap(&d_controls_p, &tmp.d_controls_p);
1588 bslalg::SwapUtil::swap(&d_size, &tmp.d_size);
1589 bslalg::SwapUtil::swap(&d_capacity, &tmp.d_capacity);
1590 bslalg::SwapUtil::swap(&d_groupControlShift, &tmp.d_groupControlShift);
1591}
1592
1593// PRIVATE ACCESSORS
1594template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1595bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::findKey(
1596 const KEY& key,
1597 bsl::size_t hashValue) const
1598{
1599 BSLS_ASSERT_SAFE(hashValue == d_hasher(key));
1600
1601 bsl::size_t index = (hashValue >> d_groupControlShift)
1602 * GroupControl::k_SIZE;
1603 bsl::uint8_t hashlet = static_cast<bsl::uint8_t>(
1604 hashValue & k_HASHLET_MASK);
1605
1606 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
1607 bsl::uint8_t *controlStart = d_controls_p + index;
1608 ENTRY *entryStart = d_entries_p + index;
1609
1610 GroupControl groupControl(controlStart);
1611 bsl::uint32_t candidates = groupControl.match(hashlet);
1612 while (candidates) {
1613 int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
1614
1615 ENTRY *entry = entryStart + offset;
1616
1618 d_equal(ENTRY_UTIL::key(*entry), key))) {
1619 return index + offset; // RETURN
1620 }
1621 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
1622 }
1623 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(groupControl.neverFull())) {
1624 break;
1625 }
1626
1627 index = (index + GroupControl::k_SIZE) & (d_capacity - 1);
1628 }
1629
1630 return d_capacity;
1631}
1632
1633template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1634bsl::size_t FlatHashTable<KEY,
1635 ENTRY,
1636 ENTRY_UTIL,
1637 HASH,
1638 EQUAL>::minimumCompliantCapacity(
1639 bsl::size_t minimumCapacity) const
1640{
1641 bsl::size_t minForEntries = ((d_size + k_MAX_LOAD_FACTOR_NUMERATOR - 1)
1642 / k_MAX_LOAD_FACTOR_NUMERATOR)
1643 * k_MAX_LOAD_FACTOR_DENOMINATOR;
1644
1645 bsl::size_t capacity = minimumCapacity >= minForEntries
1646 ? minimumCapacity
1647 : minForEntries;
1648
1649 if (0 < capacity) {
1650 capacity = capacity > k_MIN_CAPACITY
1651 ? static_cast<bsl::size_t>(bdlb::BitUtil::roundUpToBinaryPower(
1652 static_cast<bsl::uint64_t>(capacity)))
1653 : k_MIN_CAPACITY;
1654 }
1655
1656 return capacity;
1657}
1658
1659// CREATORS
1660template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1661inline
1662FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
1663 bsl::size_t capacity,
1664 const HASH& hash,
1665 const EQUAL& equal,
1666 bslma::Allocator *basicAllocator)
1667: d_entries_p(0)
1668, d_controls_p(0)
1669, d_size(0)
1670, d_capacity(0)
1671, d_groupControlShift(0)
1672, d_hasher(hash)
1673, d_equal(equal)
1674, d_allocator_p(bslma::Default::allocator(basicAllocator))
1675{
1676 if (0 < capacity) {
1677 d_capacity = capacity > k_MIN_CAPACITY
1678 ? static_cast<bsl::size_t>(bdlb::BitUtil::roundUpToBinaryPower(
1679 static_cast<bsl::uint64_t>(capacity)))
1680 : k_MIN_CAPACITY;
1681
1682 d_groupControlShift = static_cast<int>(
1683 sizeof(bsl::size_t) * 8
1684 - bdlb::BitUtil::log2(static_cast<bsl::uint64_t>(
1685 d_capacity
1686 / GroupControl::k_SIZE)));
1687
1688 ENTRY *entries = static_cast<ENTRY *>(
1689 d_allocator_p->allocate(d_capacity * sizeof(ENTRY)));
1690
1692 d_allocator_p);
1693
1694 d_controls_p = static_cast<bsl::uint8_t *>(
1695 d_allocator_p->allocate(d_capacity));
1696 bsl::memset(d_controls_p, GroupControl::k_EMPTY, d_capacity);
1697
1698 proctor.release();
1699 d_entries_p = entries;
1700 }
1701}
1702
1703template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1704inline
1705FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
1706 const FlatHashTable& original,
1707 bslma::Allocator *basicAllocator)
1708: d_entries_p(0)
1709, d_controls_p(0)
1710, d_size(0)
1711, d_capacity(0)
1712, d_groupControlShift(0)
1713, d_hasher(original.hash_function())
1714, d_equal(original.key_eq())
1715, d_allocator_p(bslma::Default::allocator(basicAllocator))
1716{
1717 if (0 != original.d_capacity) {
1718 bsl::uint8_t *const controls = static_cast<bsl::uint8_t *>(
1719 d_allocator_p->allocate(original.d_capacity));
1721 controls,
1722 d_allocator_p);
1723
1724 ENTRY *const entries = static_cast<ENTRY *>(
1725 d_allocator_p->allocate(original.d_capacity * sizeof(ENTRY)));
1727 entries,
1728 d_allocator_p);
1729
1730 ImplUtil::copyEntryAndControlArrays(
1731 entries,
1732 controls,
1733 original.d_entries_p,
1734 original.d_entries_p + original.d_capacity,
1735 original.d_controls_p,
1736 original.d_controls_p + original.d_capacity,
1737 d_allocator_p);
1738
1739 entriesProctor.release();
1740 controlsProctor.release();
1741
1742 d_entries_p = entries;
1743 d_controls_p = controls;
1744 d_size = original.d_size;
1745 d_capacity = original.d_capacity;
1746 d_groupControlShift = original.d_groupControlShift;
1747 }
1748}
1749
1750template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1751inline
1752FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
1754: d_entries_p(bslmf::MovableRefUtil::access(original).d_entries_p)
1755, d_controls_p(bslmf::MovableRefUtil::access(original).d_controls_p)
1756, d_size(bslmf::MovableRefUtil::access(original).d_size)
1757, d_capacity(bslmf::MovableRefUtil::access(original).d_capacity)
1758, d_groupControlShift(
1759 bslmf::MovableRefUtil::access(original).d_groupControlShift)
1760, d_hasher(bslmf::MovableRefUtil::access(original).d_hasher)
1761, d_equal(bslmf::MovableRefUtil::access(original).d_equal)
1762, d_allocator_p(bslmf::MovableRefUtil::access(original).d_allocator_p)
1763{
1764 FlatHashTable& reference = original;
1765
1766 reference.d_entries_p = 0;
1767 reference.d_controls_p = 0;
1768 reference.d_size = 0;
1769 reference.d_capacity = 0;
1770 reference.d_groupControlShift = 0;
1771}
1772
1773template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1774FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
1776 bslma::Allocator *basicAllocator)
1777: d_entries_p(0)
1778, d_controls_p(0)
1779, d_size(0)
1780, d_capacity(0)
1781, d_groupControlShift(0)
1782, d_hasher(bslmf::MovableRefUtil::access(original).d_hasher)
1783, d_equal(bslmf::MovableRefUtil::access(original).d_equal)
1784, d_allocator_p(bslma::Default::allocator(basicAllocator))
1785{
1786 FlatHashTable& reference = original;
1787 if (d_allocator_p == reference.d_allocator_p) {
1788 bslalg::SwapUtil::swap(&d_entries_p, &reference.d_entries_p);
1789 bslalg::SwapUtil::swap(&d_controls_p, &reference.d_controls_p);
1790 bslalg::SwapUtil::swap(&d_size, &reference.d_size);
1791 bslalg::SwapUtil::swap(&d_capacity, &reference.d_capacity);
1792 bslalg::SwapUtil::swap(&d_groupControlShift,
1793 &reference.d_groupControlShift);
1794 }
1795 else if (reference.d_capacity) {
1796 bsl::uint8_t *const controls = static_cast<bsl::uint8_t *>(
1797 d_allocator_p->allocate(reference.d_capacity));
1799 controls,
1800 d_allocator_p);
1801
1802 ENTRY *const entries = static_cast<ENTRY *>(
1803 d_allocator_p->allocate(reference.d_capacity * sizeof(ENTRY)));
1805 entries,
1806 d_allocator_p);
1807
1808 ImplUtil::copyEntryAndControlArrays(
1809 entries,
1810 controls,
1811 reference.d_entries_p,
1812 reference.d_entries_p + reference.d_capacity,
1813 reference.d_controls_p,
1814 reference.d_controls_p + reference.d_capacity,
1815 d_allocator_p);
1816
1817 entriesProctor.release();
1818 controlsProctor.release();
1819
1820 d_entries_p = entries;
1821 d_controls_p = controls;
1822 d_size = reference.d_size;
1823 d_capacity = reference.d_capacity;
1824 d_groupControlShift = reference.d_groupControlShift;
1825 }
1826}
1827
1828template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1829inline
1830FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::~FlatHashTable()
1831{
1833 (d_capacity == 0 && d_groupControlShift == 0) ||
1834 (d_groupControlShift ==
1835 static_cast<int>(sizeof(bsl::size_t) * 8 -
1836 bdlb::BitUtil::log2(static_cast<bsl::uint64_t>(
1837 d_capacity / GroupControl::k_SIZE)))));
1838
1839 if (0 != d_entries_p) {
1840 ImplUtil::destroyEntryArray(d_entries_p,
1841 d_entries_p + d_capacity,
1842 d_controls_p,
1843 d_controls_p + d_capacity);
1844
1845 d_allocator_p->deallocate(d_entries_p);
1846 d_allocator_p->deallocate(d_controls_p);
1847 }
1848}
1849
1850// MANIPULATORS
1851template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1852inline
1853FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>&
1854FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::operator=(
1855 const FlatHashTable& rhs)
1856{
1857 if (this != &rhs) {
1858 FlatHashTable tmp(rhs, d_allocator_p);
1859 swap(tmp);
1860 }
1861 return *this;
1862}
1863
1864template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1865inline
1866FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>&
1867FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::operator=(
1869{
1870 FlatHashTable& reference = rhs;
1871 if (this != &reference) {
1872 FlatHashTable table(bslmf::MovableRefUtil::move(reference),
1873 d_allocator_p);
1874 swap(table);
1875 }
1876 return *this;
1877}
1878
1879template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1880template <class KEY_TYPE>
1881inline
1882ENTRY& FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::operator[](
1884{
1885 bool notFound;
1886 bsl::size_t hashValue = d_hasher(key);
1887 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
1888
1889 if (notFound) {
1890 ENTRY_UTIL::constructFromKey(d_entries_p + index,
1891 d_allocator_p,
1892 BSLS_COMPILERFEATURES_FORWARD(KEY_TYPE, key));
1893
1894 d_controls_p[index] = static_cast<bsl::uint8_t>(
1895 hashValue & k_HASHLET_MASK);
1896
1897 ++d_size;
1898 }
1899
1900 return d_entries_p[index];
1901}
1902
1903template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1904inline
1905void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::clear()
1906{
1907 ImplUtil::destroyEntryArray(d_entries_p,
1908 d_entries_p + d_capacity,
1909 d_controls_p,
1910 d_controls_p + d_capacity);
1911
1912 if (d_controls_p) {
1913 bsl::memset(d_controls_p, GroupControl::k_EMPTY, d_capacity);
1914 }
1915
1916 d_size = 0;
1917}
1918
1919template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1920inline
1921bsl::pair<
1922 typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
1923 typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator>
1924FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::equal_range(const KEY& key)
1925{
1926 iterator it1 = find(key);
1927 if (it1 == end()) {
1928 return bsl::make_pair(it1, it1); // RETURN
1929 }
1930 iterator it2 = it1;
1931 ++it2;
1932 return bsl::make_pair(it1, it2);
1933}
1934
1935#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
1936// {{{ BEGIN GENERATED CODE
1937// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
1938#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
1939#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
1940#endif
1941#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C
1942#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C BDLC_FLATHASHTABLE_VARIADIC_LIMIT
1943#endif
1944#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 0
1945template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1946inline
1947bsl::pair<typename
1948 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
1949 bool>
1950FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
1951 )
1952{
1954 ENTRY_UTIL::construct(value.address(),
1955 d_allocator_p);
1956
1958 return this->insert(bslmf::MovableRefUtil::move(value.object()));
1959}
1960#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 0
1961
1962#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 1
1963template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1964template< class ARGS_01>
1965inline
1966bsl::pair<typename
1967 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
1968 bool>
1969FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
1970 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
1971{
1973 ENTRY_UTIL::construct(value.address(),
1974 d_allocator_p,
1975 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
1976
1978 return this->insert(bslmf::MovableRefUtil::move(value.object()));
1979}
1980#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 1
1981
1982#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 2
1983template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1984template< class ARGS_01,
1985 class ARGS_02>
1986inline
1987bsl::pair<typename
1988 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
1989 bool>
1990FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
1991 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1992 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
1993{
1995 ENTRY_UTIL::construct(value.address(),
1996 d_allocator_p,
1997 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1998 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
1999
2001 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2002}
2003#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 2
2004
2005#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 3
2006template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2007template< class ARGS_01,
2008 class ARGS_02,
2009 class ARGS_03>
2010inline
2011bsl::pair<typename
2012 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2013 bool>
2014FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2015 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2016 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2017 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
2018{
2020 ENTRY_UTIL::construct(value.address(),
2021 d_allocator_p,
2022 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2023 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2024 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
2025
2027 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2028}
2029#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 3
2030
2031#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 4
2032template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2033template< class ARGS_01,
2034 class ARGS_02,
2035 class ARGS_03,
2036 class ARGS_04>
2037inline
2038bsl::pair<typename
2039 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2040 bool>
2041FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2042 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2043 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2044 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2045 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
2046{
2048 ENTRY_UTIL::construct(value.address(),
2049 d_allocator_p,
2050 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2051 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2052 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2053 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
2054
2056 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2057}
2058#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 4
2059
2060#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 5
2061template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2062template< class ARGS_01,
2063 class ARGS_02,
2064 class ARGS_03,
2065 class ARGS_04,
2066 class ARGS_05>
2067inline
2068bsl::pair<typename
2069 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2070 bool>
2071FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2072 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2073 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2074 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2075 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2076 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
2077{
2079 ENTRY_UTIL::construct(value.address(),
2080 d_allocator_p,
2081 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2082 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2083 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2084 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2085 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05));
2086
2088 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2089}
2090#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 5
2091
2092#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 6
2093template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2094template< class ARGS_01,
2095 class ARGS_02,
2096 class ARGS_03,
2097 class ARGS_04,
2098 class ARGS_05,
2099 class ARGS_06>
2100inline
2101bsl::pair<typename
2102 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2103 bool>
2104FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2105 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2106 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2107 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2108 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2109 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2110 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
2111{
2113 ENTRY_UTIL::construct(value.address(),
2114 d_allocator_p,
2115 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2116 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2117 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2118 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2119 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2120 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
2121
2123 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2124}
2125#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 6
2126
2127#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 7
2128template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2129template< class ARGS_01,
2130 class ARGS_02,
2131 class ARGS_03,
2132 class ARGS_04,
2133 class ARGS_05,
2134 class ARGS_06,
2135 class ARGS_07>
2136inline
2137bsl::pair<typename
2138 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2139 bool>
2140FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2141 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2142 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2143 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2144 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2145 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2146 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2147 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
2148{
2150 ENTRY_UTIL::construct(value.address(),
2151 d_allocator_p,
2152 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2153 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2154 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2155 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2156 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2157 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2158 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
2159
2161 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2162}
2163#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 7
2164
2165#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 8
2166template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2167template< class ARGS_01,
2168 class ARGS_02,
2169 class ARGS_03,
2170 class ARGS_04,
2171 class ARGS_05,
2172 class ARGS_06,
2173 class ARGS_07,
2174 class ARGS_08>
2175inline
2176bsl::pair<typename
2177 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2178 bool>
2179FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2180 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2181 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2182 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2183 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2184 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2185 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2186 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2187 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
2188{
2190 ENTRY_UTIL::construct(value.address(),
2191 d_allocator_p,
2192 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2193 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2194 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2195 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2196 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2197 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2198 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2199 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
2200
2202 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2203}
2204#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 8
2205
2206#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 9
2207template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2208template< class ARGS_01,
2209 class ARGS_02,
2210 class ARGS_03,
2211 class ARGS_04,
2212 class ARGS_05,
2213 class ARGS_06,
2214 class ARGS_07,
2215 class ARGS_08,
2216 class ARGS_09>
2217inline
2218bsl::pair<typename
2219 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2220 bool>
2221FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2222 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2223 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2224 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2225 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2226 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2227 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2228 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2229 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
2230 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
2231{
2233 ENTRY_UTIL::construct(value.address(),
2234 d_allocator_p,
2235 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2236 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2237 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2238 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2239 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2240 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2241 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2242 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
2243 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
2244
2246 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2247}
2248#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 9
2249
2250#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 10
2251template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2252template< class ARGS_01,
2253 class ARGS_02,
2254 class ARGS_03,
2255 class ARGS_04,
2256 class ARGS_05,
2257 class ARGS_06,
2258 class ARGS_07,
2259 class ARGS_08,
2260 class ARGS_09,
2261 class ARGS_10>
2262inline
2263bsl::pair<typename
2264 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2265 bool>
2266FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2267 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2268 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2269 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2270 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2271 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2272 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2273 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2274 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
2275 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
2276 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
2277{
2279 ENTRY_UTIL::construct(value.address(),
2280 d_allocator_p,
2281 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2282 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2283 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2284 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2285 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2286 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2287 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2288 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
2289 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
2290 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
2291
2293 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2294}
2295#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_C >= 10
2296
2297#else
2298// The generated code below is a workaround for the absence of perfect
2299// forwarding in some compilers.
2300template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2301template< class... ARGS>
2302inline
2303bsl::pair<typename
2304 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2305 bool>
2306FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2308{
2310 ENTRY_UTIL::construct(value.address(),
2311 d_allocator_p,
2312 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
2313
2315 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2316}
2317// }}} END GENERATED CODE
2318#endif
2319
2320
2321template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2322inline
2323bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
2324 const KEY& key)
2325{
2326 iterator it = find(key);
2327 if (it == end()) {
2328 return 0; // RETURN
2329 }
2330 erase(it);
2331 return 1;
2332}
2333
2334template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2335inline
2336typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
2337FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
2338 typename FlatHashTable<KEY,
2339 ENTRY,
2340 ENTRY_UTIL,
2341 HASH,
2342 EQUAL>::const_iterator position)
2343{
2344 BSLS_ASSERT_SAFE(position != end());
2345
2346 bsl::size_t index = &*position - d_entries_p;
2347 bslma::DestructionUtil::destroy(d_entries_p + index);
2348 d_controls_p[index] = GroupControl::k_ERASED;
2349 --d_size;
2350
2351 if (d_size) {
2352 for (bsl::size_t i = index + 1; i < d_capacity; ++i) {
2353 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
2354 return iterator(IteratorImp(d_entries_p + i,
2355 d_controls_p + i,
2356 d_capacity - i - 1)); // RETURN
2357 }
2358 }
2359 }
2360 return iterator();
2361}
2362
2363template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2364inline
2365typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
2366FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
2367 typename FlatHashTable<KEY,
2368 ENTRY,
2369 ENTRY_UTIL,
2370 HASH,
2371 EQUAL>::iterator position)
2372{
2373 // Note that this overload is necessary to avoid ambiguity when the key is
2374 // a table iterator.
2375
2376 BSLS_ASSERT_SAFE(position != end());
2377
2378 bsl::size_t index = &*position - d_entries_p;
2379 bslma::DestructionUtil::destroy(d_entries_p + index);
2380 d_controls_p[index] = GroupControl::k_ERASED;
2381 --d_size;
2382
2383 if (d_size) {
2384 for (bsl::size_t i = index + 1; i < d_capacity; ++i) {
2385 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
2386 return iterator(IteratorImp(d_entries_p + i,
2387 d_controls_p + i,
2388 d_capacity - i - 1)); // RETURN
2389 }
2390 }
2391 }
2392 return iterator();
2393}
2394
2395template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2396typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
2397FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
2398 typename FlatHashTable<KEY,
2399 ENTRY,
2400 ENTRY_UTIL,
2401 HASH,
2402 EQUAL>::const_iterator first,
2403 typename FlatHashTable<KEY,
2404 ENTRY,
2405 ENTRY_UTIL,
2406 HASH,
2407 EQUAL>::const_iterator last)
2408{
2409 iterator rv;
2410 {
2411 if (last != end()) {
2412 bsl::size_t index = &*last - d_entries_p;
2413 rv = iterator(IteratorImp(d_entries_p + index,
2414 d_controls_p + index,
2415 d_capacity - index - 1));
2416 }
2417 else {
2418 rv = end();
2419 }
2420 }
2421
2422 for (; first != last; ++first) {
2423 erase(first);
2424 }
2425
2426 return rv;
2427}
2428
2429template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2430inline
2431typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
2432FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::find(const KEY& key)
2433{
2434 bsl::size_t index = findKey(key, d_hasher(key));
2435 if (index < d_capacity) {
2436 return iterator(IteratorImp(d_entries_p + index,
2437 d_controls_p + index,
2438 d_capacity - index - 1)); // RETURN
2439 }
2440 return end();
2441}
2442
2443template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2444template <class INPUT_ITERATOR>
2445inline
2446void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::insert(
2447 INPUT_ITERATOR first,
2448 INPUT_ITERATOR last)
2449{
2450 for (; first != last; ++first) {
2451 insert(*first);
2452 }
2453}
2454
2455template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2456inline
2457void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::rehash(
2458 bsl::size_t minimumCapacity)
2459{
2460 minimumCapacity = minimumCompliantCapacity(minimumCapacity);
2461
2462 if (0 < minimumCapacity) {
2463 rehashRaw(minimumCapacity);
2464 }
2465 else {
2466 d_allocator_p->deallocate(d_entries_p);
2467 d_allocator_p->deallocate(d_controls_p);
2468
2469 d_entries_p = 0;
2470 d_controls_p = 0;
2471 d_capacity = 0;
2472 d_groupControlShift = 0;
2473 }
2474}
2475
2476template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2477inline
2478void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::reserve(
2479 bsl::size_t numEntries)
2480{
2481 if (0 == d_capacity && 0 == numEntries) {
2482 // From DRQS 167247593, 'reserve(0)' on an empty container is a
2483 // performance concern.
2484
2485 return; // RETURN
2486 }
2487
2488 bsl::size_t minForEntries = ((numEntries + k_MAX_LOAD_FACTOR_NUMERATOR - 1)
2489 / k_MAX_LOAD_FACTOR_NUMERATOR)
2490 * k_MAX_LOAD_FACTOR_DENOMINATOR;
2491
2492 rehash(minForEntries);
2493}
2494
2495template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2496inline
2497void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::reset()
2498{
2499 if (0 != d_entries_p) {
2500 ImplUtil::destroyEntryArray(d_entries_p,
2501 d_entries_p + d_capacity,
2502 d_controls_p,
2503 d_controls_p + d_capacity);
2504
2505 d_allocator_p->deallocate(d_entries_p);
2506 d_allocator_p->deallocate(d_controls_p);
2507
2508 d_entries_p = 0;
2509 d_controls_p = 0;
2510 d_capacity = 0;
2511 d_size = 0;
2512 d_groupControlShift = 0;
2513 }
2514}
2515
2516#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
2517// {{{ BEGIN GENERATED CODE
2518// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
2519#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
2520#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
2521#endif
2522#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D
2523#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D BDLC_FLATHASHTABLE_VARIADIC_LIMIT
2524#endif
2525#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
2526template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2527bsl::pair<typename
2528 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2529 bool>
2530FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2531 const KEY& key)
2532{
2533 bool notFound;
2534 bsl::size_t hashValue = d_hasher(key);
2535 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2536
2537 if (notFound) {
2538 ENTRY_UTIL::construct(d_entries_p + index,
2539 d_allocator_p);
2540
2541 d_controls_p[index] = static_cast<bsl::uint8_t>(
2542 hashValue & k_HASHLET_MASK);
2543 ++d_size;
2544 }
2545
2546 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2547 d_controls_p + index,
2548 d_capacity - index - 1),
2549 notFound);
2550}
2551#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
2552
2553#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
2554template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2555template< class ARGS_01>
2556bsl::pair<typename
2557 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2558 bool>
2559FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2560 const KEY& key,
2561 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
2562{
2563 bool notFound;
2564 bsl::size_t hashValue = d_hasher(key);
2565 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2566
2567 if (notFound) {
2568 ENTRY_UTIL::construct(d_entries_p + index,
2569 d_allocator_p,
2570 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
2571
2572 d_controls_p[index] = static_cast<bsl::uint8_t>(
2573 hashValue & k_HASHLET_MASK);
2574 ++d_size;
2575 }
2576
2577 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2578 d_controls_p + index,
2579 d_capacity - index - 1),
2580 notFound);
2581}
2582#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
2583
2584#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
2585template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2586template< class ARGS_01,
2587 class ARGS_02>
2588bsl::pair<typename
2589 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2590 bool>
2591FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2592 const KEY& key,
2593 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2594 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
2595{
2596 bool notFound;
2597 bsl::size_t hashValue = d_hasher(key);
2598 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2599
2600 if (notFound) {
2601 ENTRY_UTIL::construct(d_entries_p + index,
2602 d_allocator_p,
2603 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2604 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
2605
2606 d_controls_p[index] = static_cast<bsl::uint8_t>(
2607 hashValue & k_HASHLET_MASK);
2608 ++d_size;
2609 }
2610
2611 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2612 d_controls_p + index,
2613 d_capacity - index - 1),
2614 notFound);
2615}
2616#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
2617
2618#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
2619template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2620template< class ARGS_01,
2621 class ARGS_02,
2622 class ARGS_03>
2623bsl::pair<typename
2624 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2625 bool>
2626FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2627 const KEY& key,
2628 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2629 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2630 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
2631{
2632 bool notFound;
2633 bsl::size_t hashValue = d_hasher(key);
2634 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2635
2636 if (notFound) {
2637 ENTRY_UTIL::construct(d_entries_p + index,
2638 d_allocator_p,
2639 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2640 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2641 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
2642
2643 d_controls_p[index] = static_cast<bsl::uint8_t>(
2644 hashValue & k_HASHLET_MASK);
2645 ++d_size;
2646 }
2647
2648 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2649 d_controls_p + index,
2650 d_capacity - index - 1),
2651 notFound);
2652}
2653#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
2654
2655#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
2656template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2657template< class ARGS_01,
2658 class ARGS_02,
2659 class ARGS_03,
2660 class ARGS_04>
2661bsl::pair<typename
2662 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2663 bool>
2664FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2665 const KEY& key,
2666 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2667 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2668 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2669 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
2670{
2671 bool notFound;
2672 bsl::size_t hashValue = d_hasher(key);
2673 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2674
2675 if (notFound) {
2676 ENTRY_UTIL::construct(d_entries_p + index,
2677 d_allocator_p,
2678 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2679 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2680 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2681 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
2682
2683 d_controls_p[index] = static_cast<bsl::uint8_t>(
2684 hashValue & k_HASHLET_MASK);
2685 ++d_size;
2686 }
2687
2688 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2689 d_controls_p + index,
2690 d_capacity - index - 1),
2691 notFound);
2692}
2693#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
2694
2695#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
2696template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2697template< class ARGS_01,
2698 class ARGS_02,
2699 class ARGS_03,
2700 class ARGS_04,
2701 class ARGS_05>
2702bsl::pair<typename
2703 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2704 bool>
2705FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2706 const KEY& key,
2707 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2708 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2709 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2710 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2711 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
2712{
2713 bool notFound;
2714 bsl::size_t hashValue = d_hasher(key);
2715 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2716
2717 if (notFound) {
2718 ENTRY_UTIL::construct(d_entries_p + index,
2719 d_allocator_p,
2720 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2721 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2722 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2723 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2724 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05));
2725
2726 d_controls_p[index] = static_cast<bsl::uint8_t>(
2727 hashValue & k_HASHLET_MASK);
2728 ++d_size;
2729 }
2730
2731 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2732 d_controls_p + index,
2733 d_capacity - index - 1),
2734 notFound);
2735}
2736#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
2737
2738#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
2739template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2740template< class ARGS_01,
2741 class ARGS_02,
2742 class ARGS_03,
2743 class ARGS_04,
2744 class ARGS_05,
2745 class ARGS_06>
2746bsl::pair<typename
2747 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2748 bool>
2749FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2750 const KEY& key,
2751 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2752 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2753 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2754 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2755 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2756 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
2757{
2758 bool notFound;
2759 bsl::size_t hashValue = d_hasher(key);
2760 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2761
2762 if (notFound) {
2763 ENTRY_UTIL::construct(d_entries_p + index,
2764 d_allocator_p,
2765 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2766 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2767 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2768 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2769 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2770 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
2771
2772 d_controls_p[index] = static_cast<bsl::uint8_t>(
2773 hashValue & k_HASHLET_MASK);
2774 ++d_size;
2775 }
2776
2777 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2778 d_controls_p + index,
2779 d_capacity - index - 1),
2780 notFound);
2781}
2782#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
2783
2784#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
2785template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2786template< class ARGS_01,
2787 class ARGS_02,
2788 class ARGS_03,
2789 class ARGS_04,
2790 class ARGS_05,
2791 class ARGS_06,
2792 class ARGS_07>
2793bsl::pair<typename
2794 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2795 bool>
2796FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2797 const KEY& key,
2798 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2799 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2800 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2801 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2802 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2803 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2804 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
2805{
2806 bool notFound;
2807 bsl::size_t hashValue = d_hasher(key);
2808 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2809
2810 if (notFound) {
2811 ENTRY_UTIL::construct(d_entries_p + index,
2812 d_allocator_p,
2813 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2814 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2815 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2816 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2817 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2818 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2819 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
2820
2821 d_controls_p[index] = static_cast<bsl::uint8_t>(
2822 hashValue & k_HASHLET_MASK);
2823 ++d_size;
2824 }
2825
2826 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2827 d_controls_p + index,
2828 d_capacity - index - 1),
2829 notFound);
2830}
2831#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
2832
2833#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
2834template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2835template< class ARGS_01,
2836 class ARGS_02,
2837 class ARGS_03,
2838 class ARGS_04,
2839 class ARGS_05,
2840 class ARGS_06,
2841 class ARGS_07,
2842 class ARGS_08>
2843bsl::pair<typename
2844 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2845 bool>
2846FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2847 const KEY& key,
2848 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2849 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2850 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2851 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2852 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2853 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2854 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2855 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
2856{
2857 bool notFound;
2858 bsl::size_t hashValue = d_hasher(key);
2859 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2860
2861 if (notFound) {
2862 ENTRY_UTIL::construct(d_entries_p + index,
2863 d_allocator_p,
2864 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2865 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2866 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2867 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2868 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2869 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2870 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2871 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
2872
2873 d_controls_p[index] = static_cast<bsl::uint8_t>(
2874 hashValue & k_HASHLET_MASK);
2875 ++d_size;
2876 }
2877
2878 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2879 d_controls_p + index,
2880 d_capacity - index - 1),
2881 notFound);
2882}
2883#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
2884
2885#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
2886template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2887template< class ARGS_01,
2888 class ARGS_02,
2889 class ARGS_03,
2890 class ARGS_04,
2891 class ARGS_05,
2892 class ARGS_06,
2893 class ARGS_07,
2894 class ARGS_08,
2895 class ARGS_09>
2896bsl::pair<typename
2897 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2898 bool>
2899FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2900 const KEY& key,
2901 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2902 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2903 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2904 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2905 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2906 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2907 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2908 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
2909 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
2910{
2911 bool notFound;
2912 bsl::size_t hashValue = d_hasher(key);
2913 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2914
2915 if (notFound) {
2916 ENTRY_UTIL::construct(d_entries_p + index,
2917 d_allocator_p,
2918 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2919 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2920 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2921 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2922 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2923 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2924 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2925 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
2926 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
2927
2928 d_controls_p[index] = static_cast<bsl::uint8_t>(
2929 hashValue & k_HASHLET_MASK);
2930 ++d_size;
2931 }
2932
2933 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2934 d_controls_p + index,
2935 d_capacity - index - 1),
2936 notFound);
2937}
2938#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
2939
2940#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
2941template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2942template< class ARGS_01,
2943 class ARGS_02,
2944 class ARGS_03,
2945 class ARGS_04,
2946 class ARGS_05,
2947 class ARGS_06,
2948 class ARGS_07,
2949 class ARGS_08,
2950 class ARGS_09,
2951 class ARGS_10>
2952bsl::pair<typename
2953 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2954 bool>
2955FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
2956 const KEY& key,
2957 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2958 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2959 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2960 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2961 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2962 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2963 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2964 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
2965 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
2966 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
2967{
2968 bool notFound;
2969 bsl::size_t hashValue = d_hasher(key);
2970 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2971
2972 if (notFound) {
2973 ENTRY_UTIL::construct(d_entries_p + index,
2974 d_allocator_p,
2975 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2976 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2977 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2978 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2979 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2980 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2981 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2982 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
2983 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
2984 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
2985
2986 d_controls_p[index] = static_cast<bsl::uint8_t>(
2987 hashValue & k_HASHLET_MASK);
2988 ++d_size;
2989 }
2990
2991 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
2992 d_controls_p + index,
2993 d_capacity - index - 1),
2994 notFound);
2995}
2996#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
2997
2998
2999#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
3000template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3001bsl::pair<typename
3002 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3003 bool>
3004FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3005 BloombergLP::bslmf::MovableRef<KEY> key)
3006{
3007 const KEY& k = key;
3008 bool notFound;
3009 bsl::size_t hashValue = d_hasher(k);
3010 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3011
3012 if (notFound) {
3013 ENTRY_UTIL::construct(d_entries_p + index,
3014 d_allocator_p);
3015
3016 d_controls_p[index] = static_cast<bsl::uint8_t>(
3017 hashValue & k_HASHLET_MASK);
3018 ++d_size;
3019 }
3020 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3021 d_controls_p + index,
3022 d_capacity - index - 1),
3023 notFound);
3024}
3025#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
3026
3027#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
3028template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3029template< class ARGS_01>
3030bsl::pair<typename
3031 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3032 bool>
3033FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3034 BloombergLP::bslmf::MovableRef<KEY> key,
3035 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
3036{
3037 const KEY& k = key;
3038 bool notFound;
3039 bsl::size_t hashValue = d_hasher(k);
3040 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3041
3042 if (notFound) {
3043 ENTRY_UTIL::construct(d_entries_p + index,
3044 d_allocator_p,
3045 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
3046
3047 d_controls_p[index] = static_cast<bsl::uint8_t>(
3048 hashValue & k_HASHLET_MASK);
3049 ++d_size;
3050 }
3051 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3052 d_controls_p + index,
3053 d_capacity - index - 1),
3054 notFound);
3055}
3056#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
3057
3058#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
3059template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3060template< class ARGS_01,
3061 class ARGS_02>
3062bsl::pair<typename
3063 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3064 bool>
3065FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3066 BloombergLP::bslmf::MovableRef<KEY> key,
3067 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3068 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
3069{
3070 const KEY& k = key;
3071 bool notFound;
3072 bsl::size_t hashValue = d_hasher(k);
3073 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3074
3075 if (notFound) {
3076 ENTRY_UTIL::construct(d_entries_p + index,
3077 d_allocator_p,
3078 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3079 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
3080
3081 d_controls_p[index] = static_cast<bsl::uint8_t>(
3082 hashValue & k_HASHLET_MASK);
3083 ++d_size;
3084 }
3085 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3086 d_controls_p + index,
3087 d_capacity - index - 1),
3088 notFound);
3089}
3090#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
3091
3092#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
3093template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3094template< class ARGS_01,
3095 class ARGS_02,
3096 class ARGS_03>
3097bsl::pair<typename
3098 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3099 bool>
3100FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3101 BloombergLP::bslmf::MovableRef<KEY> key,
3102 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3103 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3104 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
3105{
3106 const KEY& k = key;
3107 bool notFound;
3108 bsl::size_t hashValue = d_hasher(k);
3109 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3110
3111 if (notFound) {
3112 ENTRY_UTIL::construct(d_entries_p + index,
3113 d_allocator_p,
3114 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3115 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3116 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
3117
3118 d_controls_p[index] = static_cast<bsl::uint8_t>(
3119 hashValue & k_HASHLET_MASK);
3120 ++d_size;
3121 }
3122 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3123 d_controls_p + index,
3124 d_capacity - index - 1),
3125 notFound);
3126}
3127#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
3128
3129#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
3130template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3131template< class ARGS_01,
3132 class ARGS_02,
3133 class ARGS_03,
3134 class ARGS_04>
3135bsl::pair<typename
3136 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3137 bool>
3138FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3139 BloombergLP::bslmf::MovableRef<KEY> key,
3140 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3141 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3142 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3143 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
3144{
3145 const KEY& k = key;
3146 bool notFound;
3147 bsl::size_t hashValue = d_hasher(k);
3148 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3149
3150 if (notFound) {
3151 ENTRY_UTIL::construct(d_entries_p + index,
3152 d_allocator_p,
3153 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3154 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3155 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3156 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
3157
3158 d_controls_p[index] = static_cast<bsl::uint8_t>(
3159 hashValue & k_HASHLET_MASK);
3160 ++d_size;
3161 }
3162 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3163 d_controls_p + index,
3164 d_capacity - index - 1),
3165 notFound);
3166}
3167#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
3168
3169#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
3170template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3171template< class ARGS_01,
3172 class ARGS_02,
3173 class ARGS_03,
3174 class ARGS_04,
3175 class ARGS_05>
3176bsl::pair<typename
3177 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3178 bool>
3179FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3180 BloombergLP::bslmf::MovableRef<KEY> key,
3181 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3182 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3183 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3184 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3185 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
3186{
3187 const KEY& k = key;
3188 bool notFound;
3189 bsl::size_t hashValue = d_hasher(k);
3190 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3191
3192 if (notFound) {
3193 ENTRY_UTIL::construct(d_entries_p + index,
3194 d_allocator_p,
3195 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3196 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3197 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3198 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3199 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05));
3200
3201 d_controls_p[index] = static_cast<bsl::uint8_t>(
3202 hashValue & k_HASHLET_MASK);
3203 ++d_size;
3204 }
3205 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3206 d_controls_p + index,
3207 d_capacity - index - 1),
3208 notFound);
3209}
3210#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
3211
3212#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
3213template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3214template< class ARGS_01,
3215 class ARGS_02,
3216 class ARGS_03,
3217 class ARGS_04,
3218 class ARGS_05,
3219 class ARGS_06>
3220bsl::pair<typename
3221 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3222 bool>
3223FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3224 BloombergLP::bslmf::MovableRef<KEY> key,
3225 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3226 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3227 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3228 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3229 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3230 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
3231{
3232 const KEY& k = key;
3233 bool notFound;
3234 bsl::size_t hashValue = d_hasher(k);
3235 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3236
3237 if (notFound) {
3238 ENTRY_UTIL::construct(d_entries_p + index,
3239 d_allocator_p,
3240 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3241 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3242 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3243 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3244 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3245 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
3246
3247 d_controls_p[index] = static_cast<bsl::uint8_t>(
3248 hashValue & k_HASHLET_MASK);
3249 ++d_size;
3250 }
3251 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3252 d_controls_p + index,
3253 d_capacity - index - 1),
3254 notFound);
3255}
3256#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
3257
3258#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
3259template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3260template< class ARGS_01,
3261 class ARGS_02,
3262 class ARGS_03,
3263 class ARGS_04,
3264 class ARGS_05,
3265 class ARGS_06,
3266 class ARGS_07>
3267bsl::pair<typename
3268 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3269 bool>
3270FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3271 BloombergLP::bslmf::MovableRef<KEY> key,
3272 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3273 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3274 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3275 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3276 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3277 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3278 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
3279{
3280 const KEY& k = key;
3281 bool notFound;
3282 bsl::size_t hashValue = d_hasher(k);
3283 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3284
3285 if (notFound) {
3286 ENTRY_UTIL::construct(d_entries_p + index,
3287 d_allocator_p,
3288 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3289 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3290 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3291 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3292 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3293 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3294 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
3295
3296 d_controls_p[index] = static_cast<bsl::uint8_t>(
3297 hashValue & k_HASHLET_MASK);
3298 ++d_size;
3299 }
3300 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3301 d_controls_p + index,
3302 d_capacity - index - 1),
3303 notFound);
3304}
3305#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
3306
3307#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
3308template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3309template< class ARGS_01,
3310 class ARGS_02,
3311 class ARGS_03,
3312 class ARGS_04,
3313 class ARGS_05,
3314 class ARGS_06,
3315 class ARGS_07,
3316 class ARGS_08>
3317bsl::pair<typename
3318 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3319 bool>
3320FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3321 BloombergLP::bslmf::MovableRef<KEY> key,
3322 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3323 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3324 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3325 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3326 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3327 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3328 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3329 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
3330{
3331 const KEY& k = key;
3332 bool notFound;
3333 bsl::size_t hashValue = d_hasher(k);
3334 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3335
3336 if (notFound) {
3337 ENTRY_UTIL::construct(d_entries_p + index,
3338 d_allocator_p,
3339 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3340 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3341 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3342 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3343 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3344 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3345 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3346 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
3347
3348 d_controls_p[index] = static_cast<bsl::uint8_t>(
3349 hashValue & k_HASHLET_MASK);
3350 ++d_size;
3351 }
3352 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3353 d_controls_p + index,
3354 d_capacity - index - 1),
3355 notFound);
3356}
3357#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
3358
3359#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
3360template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3361template< class ARGS_01,
3362 class ARGS_02,
3363 class ARGS_03,
3364 class ARGS_04,
3365 class ARGS_05,
3366 class ARGS_06,
3367 class ARGS_07,
3368 class ARGS_08,
3369 class ARGS_09>
3370bsl::pair<typename
3371 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3372 bool>
3373FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3374 BloombergLP::bslmf::MovableRef<KEY> key,
3375 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3376 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3377 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3378 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3379 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3380 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3381 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3382 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
3383 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
3384{
3385 const KEY& k = key;
3386 bool notFound;
3387 bsl::size_t hashValue = d_hasher(k);
3388 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3389
3390 if (notFound) {
3391 ENTRY_UTIL::construct(d_entries_p + index,
3392 d_allocator_p,
3393 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3394 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3395 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3396 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3397 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3398 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3399 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3400 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
3401 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
3402
3403 d_controls_p[index] = static_cast<bsl::uint8_t>(
3404 hashValue & k_HASHLET_MASK);
3405 ++d_size;
3406 }
3407 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3408 d_controls_p + index,
3409 d_capacity - index - 1),
3410 notFound);
3411}
3412#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
3413
3414#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
3415template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3416template< class ARGS_01,
3417 class ARGS_02,
3418 class ARGS_03,
3419 class ARGS_04,
3420 class ARGS_05,
3421 class ARGS_06,
3422 class ARGS_07,
3423 class ARGS_08,
3424 class ARGS_09,
3425 class ARGS_10>
3426bsl::pair<typename
3427 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3428 bool>
3429FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3430 BloombergLP::bslmf::MovableRef<KEY> key,
3431 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3432 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3433 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3434 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3435 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3436 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3437 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3438 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
3439 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
3440 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
3441{
3442 const KEY& k = key;
3443 bool notFound;
3444 bsl::size_t hashValue = d_hasher(k);
3445 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3446
3447 if (notFound) {
3448 ENTRY_UTIL::construct(d_entries_p + index,
3449 d_allocator_p,
3450 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3451 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3452 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3453 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3454 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3455 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3456 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3457 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
3458 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
3459 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
3460
3461 d_controls_p[index] = static_cast<bsl::uint8_t>(
3462 hashValue & k_HASHLET_MASK);
3463 ++d_size;
3464 }
3465 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3466 d_controls_p + index,
3467 d_capacity - index - 1),
3468 notFound);
3469}
3470#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
3471
3472#else
3473// The generated code below is a workaround for the absence of perfect
3474// forwarding in some compilers.
3475template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3476template< class... ARGS>
3477bsl::pair<typename
3478 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3479 bool>
3480FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3481 const KEY& key,
3483{
3484 bool notFound;
3485 bsl::size_t hashValue = d_hasher(key);
3486 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3487
3488 if (notFound) {
3489 ENTRY_UTIL::construct(d_entries_p + index,
3490 d_allocator_p,
3491 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3492
3493 d_controls_p[index] = static_cast<bsl::uint8_t>(
3494 hashValue & k_HASHLET_MASK);
3495 ++d_size;
3496 }
3497
3498 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3499 d_controls_p + index,
3500 d_capacity - index - 1),
3501 notFound);
3502}
3503
3504template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3505template< class... ARGS>
3506bsl::pair<typename
3507 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3508 bool>
3509FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3510 BloombergLP::bslmf::MovableRef<KEY> key,
3512{
3513 const KEY& k = key;
3514 bool notFound;
3515 bsl::size_t hashValue = d_hasher(k);
3516 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3517
3518 if (notFound) {
3519 ENTRY_UTIL::construct(d_entries_p + index,
3520 d_allocator_p,
3521 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3522
3523 d_controls_p[index] = static_cast<bsl::uint8_t>(
3524 hashValue & k_HASHLET_MASK);
3525 ++d_size;
3526 }
3527 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3528 d_controls_p + index,
3529 d_capacity - index - 1),
3530 notFound);
3531}
3532// }}} END GENERATED CODE
3533#endif
3534
3535 // Iterators
3536
3537template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3538inline
3539typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
3540FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::begin()
3541{
3542 if (d_size) {
3543 for (bsl::size_t i = 0; i < d_capacity; ++i) {
3544 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
3545 return iterator(IteratorImp(d_entries_p + i,
3546 d_controls_p + i,
3547 d_capacity - i - 1)); // RETURN
3548 }
3549 }
3550 }
3551 return iterator();
3552}
3553
3554template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3555inline
3556typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
3557FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::end()
3558{
3559 return iterator();
3560}
3561
3562 // Aspects
3563
3564template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3565inline
3566void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::swap(
3567 FlatHashTable& other)
3568{
3569 BSLS_ASSERT_SAFE(allocator() == other.allocator());
3570
3571 bslalg::SwapUtil::swap(&d_entries_p, &other.d_entries_p);
3572 bslalg::SwapUtil::swap(&d_controls_p, &other.d_controls_p);
3573 bslalg::SwapUtil::swap(&d_size, &other.d_size);
3574 bslalg::SwapUtil::swap(&d_capacity, &other.d_capacity);
3575 bslalg::SwapUtil::swap(&d_groupControlShift, &other.d_groupControlShift);
3576 bslalg::SwapUtil::swap(&d_hasher, &other.d_hasher);
3577 bslalg::SwapUtil::swap(&d_equal, &other.d_equal);
3578}
3579
3580// ACCESSORS
3581template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3582inline
3583bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::
3584 capacity() const
3585{
3586 return d_capacity;
3587}
3588
3589template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3590inline
3591bool FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::contains(
3592 const KEY& key) const
3593{
3594 return find(key) != end();
3595}
3596
3597template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3598inline
3599const bsl::uint8_t *FlatHashTable<KEY,
3600 ENTRY,
3601 ENTRY_UTIL,
3602 HASH,
3603 EQUAL>::controls() const
3604{
3605 return d_controls_p;
3606}
3607
3608template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3609inline
3610bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::count(
3611 const KEY& key) const
3612{
3613 return contains(key) ? 1 : 0;
3614}
3615
3616template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3617inline
3618bool FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::empty() const
3619{
3620 return 0 == d_size;
3621}
3622
3623template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3624inline
3625const ENTRY *FlatHashTable<KEY,
3626 ENTRY,
3627 ENTRY_UTIL,
3628 HASH,
3629 EQUAL>::entries() const
3630{
3631 return d_entries_p;
3632}
3633
3634template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3635inline
3636bsl::pair<typename FlatHashTable<KEY,
3637 ENTRY,
3638 ENTRY_UTIL,
3639 HASH,
3640 EQUAL>::const_iterator,
3641 typename FlatHashTable<KEY,
3642 ENTRY,
3643 ENTRY_UTIL,
3644 HASH,
3645 EQUAL>::const_iterator>
3646FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::equal_range(
3647 const KEY& key) const
3648{
3649 const_iterator cit1 = find(key);
3650 const_iterator cit2 = cit1;
3651 if (cit1 != end()) {
3652 ++cit2;
3653 }
3654 return bsl::make_pair(cit1, cit2);
3655}
3656
3657template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3658inline
3659typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
3660FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::find(const KEY& key) const
3661{
3662 bsl::size_t index = findKey(key, d_hasher(key));
3663 if (index < d_capacity) {
3664 return const_iterator(IteratorImp(d_entries_p + index,
3665 d_controls_p + index,
3666 d_capacity - index - 1)); // RETURN
3667 }
3668 return end();
3669}
3670
3671template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3672inline
3673HASH FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::hash_function() const
3674{
3675 return d_hasher;
3676}
3677
3678template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3679inline
3680EQUAL FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::key_eq() const
3681{
3682 return d_equal;
3683}
3684
3685template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3686inline
3687float bdlc::FlatHashTable<KEY,
3688 ENTRY,
3689 ENTRY_UTIL,
3690 HASH,
3691 EQUAL>::load_factor() const
3692{
3693 return d_capacity > 0
3694 ? static_cast<float>(d_size) / static_cast<float>(d_capacity)
3695 : 0;
3696}
3697
3698template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3699inline
3700float bdlc::FlatHashTable<KEY,
3701 ENTRY,
3702 ENTRY_UTIL,
3703 HASH,
3704 EQUAL>::max_load_factor() const
3705{
3706 return static_cast<float>(k_MAX_LOAD_FACTOR_NUMERATOR)
3707 / static_cast<float>(k_MAX_LOAD_FACTOR_DENOMINATOR);
3708}
3709
3710template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3711inline
3712bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::size() const
3713{
3714 return d_size;
3715}
3716
3717 // Iterators
3718
3719template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3720inline
3721typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
3722FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::begin() const
3723{
3724 if (d_size) {
3725 for (bsl::size_t i = 0; i < d_capacity; ++i) {
3726 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
3727 return const_iterator(
3728 IteratorImp(d_entries_p + i,
3729 d_controls_p + i,
3730 d_capacity - i - 1)); // RETURN
3731 }
3732 }
3733 }
3734 return const_iterator();
3735}
3736
3737template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3738inline
3739typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
3740FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::cbegin() const
3741{
3742 return begin();
3743}
3744
3745template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3746inline
3747typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
3748FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::cend() const
3749{
3750 return end();
3751}
3752
3753template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3754inline
3755typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
3756FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::end() const
3757{
3758 return const_iterator();
3759}
3760
3761 // Aspects
3762
3763template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3764inline
3765bslma::Allocator *FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::
3766 allocator() const
3767{
3768 return d_allocator_p;
3769}
3770
3771} // close package namespace
3772
3773// FREE OPERATORS
3774template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3775bool bdlc::operator==(const FlatHashTable<KEY,
3776 ENTRY,
3777 ENTRY_UTIL,
3778 HASH,
3779 EQUAL>& lhs,
3780 const FlatHashTable<KEY,
3781 ENTRY,
3782 ENTRY_UTIL,
3783 HASH,
3784 EQUAL>& rhs)
3785{
3786 typedef typename FlatHashTable<KEY,
3787 ENTRY,
3788 ENTRY_UTIL,
3789 HASH,
3790 EQUAL>::const_iterator ConstIterator;
3791
3792 if (lhs.size() == rhs.size()) {
3793 ConstIterator lhsEnd = lhs.end();
3794 ConstIterator rhsEnd = rhs.end();
3795
3796 if (lhs.capacity() <= rhs.capacity()) {
3797 for (ConstIterator it = lhs.begin(); it != lhsEnd; ++it) {
3798 ConstIterator i = rhs.find(ENTRY_UTIL::key(*it));
3799 if (i == rhsEnd || *i != *it) {
3800 return false; // RETURN
3801 }
3802 }
3803 return true; // RETURN
3804 }
3805 else {
3806 for (ConstIterator it = rhs.begin(); it != rhsEnd; ++it) {
3807 ConstIterator i = lhs.find(ENTRY_UTIL::key(*it));
3808 if (i == lhsEnd || *i != *it) {
3809 return false; // RETURN
3810 }
3811 }
3812 return true; // RETURN
3813 }
3814 }
3815 return false;
3816}
3817
3818template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3819bool bdlc::operator!=(const FlatHashTable<KEY,
3820 ENTRY,
3821 ENTRY_UTIL,
3822 HASH,
3823 EQUAL>& lhs,
3824 const FlatHashTable<KEY,
3825 ENTRY,
3826 ENTRY_UTIL,
3827 HASH,
3828 EQUAL>& rhs)
3829{
3830 return !(lhs == rhs);
3831}
3832
3833// FREE FUNCTIONS
3834template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3835inline
3836void bdlc::swap(FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& a,
3837 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& b)
3838{
3839 if (a.allocator() == b.allocator()) {
3840 a.swap(b);
3841
3842 return; // RETURN
3843 }
3844
3845 typedef FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL> Table;
3846
3847 Table futureA(b, a.allocator());
3848 Table futureB(a, b.allocator());
3849
3850 futureA.swap(a);
3851 futureB.swap(b);
3852}
3853
3854namespace bslma {
3855
3856template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3857struct UsesBslmaAllocator<bdlc::FlatHashTable<KEY,
3858 ENTRY,
3859 ENTRY_UTIL,
3860 HASH,
3861 EQUAL> > : bsl::true_type {
3862};
3863
3864} // close namespace bslma
3865
3866namespace bdlc {
3867
3868 // -----------------------------
3869 // struct FlatHashTable_ImplUtil
3870 // -----------------------------
3871
3872// PRIVATE CLASS METHODS
3873template <class ENTRY_TYPE>
3874inline
3875void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
3876 ENTRY_TYPE *firstDestinationEntry,
3877 bsl::uint8_t *firstDestinationControl,
3878 const ENTRY_TYPE *firstSourceEntry,
3879 const ENTRY_TYPE *lastSourceEntry,
3880 const bsl::uint8_t *firstSourceControl,
3881 const bsl::uint8_t *lastSourceControl,
3882 bslma::Allocator *entryAllocator,
3883 bsl::false_type isBitwiseCopyable)
3884{
3885 (void) isBitwiseCopyable;
3886
3888
3889 bsl::memcpy(firstDestinationControl,
3890 firstSourceControl,
3891 bsl::distance(firstSourceControl, lastSourceControl) *
3892 sizeof(bsl::uint8_t));
3893
3894 const bsl::size_t numEntries = static_cast<bsl::size_t>(
3895 bsl::distance(firstSourceEntry, lastSourceEntry));
3896
3897 DestroyEntryArrayProctor<ENTRY_TYPE> destroyEntriesProctor(
3898 firstDestinationEntry,
3899 firstDestinationEntry,
3900 firstDestinationControl,
3901 firstDestinationControl);
3902
3903 for (bsl::size_t idx = 0; idx != numEntries; ++idx) {
3904 ENTRY_TYPE& destinationEntry = *(firstDestinationEntry + idx);
3905 const bsl::uint8_t& sourceControl = *(firstSourceControl + idx);
3906 const ENTRY_TYPE& sourceEntry = *(firstSourceEntry + idx);
3907
3908 if (0 == (sourceControl & GroupControl::k_EMPTY)) {
3910 &destinationEntry, entryAllocator, sourceEntry);
3911 }
3912
3913 destroyEntriesProctor.moveEnd(1);
3914 }
3915
3916 destroyEntriesProctor.release();
3917}
3918
3919template <class ENTRY_TYPE>
3920inline
3921void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
3922 ENTRY_TYPE *firstDestinationEntry,
3923 bsl::uint8_t *firstDestinationControl,
3924 const ENTRY_TYPE *firstSourceEntry,
3925 const ENTRY_TYPE *lastSourceEntry,
3926 const bsl::uint8_t *firstSourceControl,
3927 const bsl::uint8_t *lastSourceControl,
3929 bsl::true_type isBitwiseCopyable)
3930{
3931 (void) isBitwiseCopyable;
3932
3934
3935 bsl::memcpy(firstDestinationControl,
3936 firstSourceControl,
3937 bsl::distance(firstSourceControl, lastSourceControl) *
3938 sizeof(bsl::uint8_t));
3939
3940#if defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000
3941#pragma GCC diagnostic push
3942#pragma GCC diagnostic ignored "-Wclass-memaccess"
3943#endif
3944
3945 bsl::memcpy(firstDestinationEntry,
3946 firstSourceEntry,
3947 bsl::distance(firstSourceEntry, lastSourceEntry) *
3948 sizeof(ENTRY_TYPE));
3949
3950#if defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000
3951#pragma GCC diagnostic pop
3952#endif
3953}
3954
3955template <class ENTRY_TYPE>
3956inline
3957void FlatHashTable_ImplUtil::destroyEntryArray(
3958 ENTRY_TYPE *firstEntry,
3959 ENTRY_TYPE *lastEntry,
3960 const bsl::uint8_t *firstControl,
3961 const bsl::uint8_t *lastControl,
3962 bsl::false_type triviallyDestructible)
3963{
3964 (void) triviallyDestructible;
3965
3966 ///Implementation Note
3967 ///-------------------
3968 // The implementation of this function uses the
3969 // 'FlatHashTable_GroupControl' facilities to bulk search through the
3970 // control range and look for entries that need to be destroyed. However,
3971 // the size of the ranges passed to this function are not always a multiple
3972 // of 'GroupControl::k_SIZE', and so a second loop is needed to
3973 // sequentially destroy the up-to 'GroupControl::k_SIZE - 1' number of
3974 // entries that cannot be destroyed as part of a bulk operation on
3975 // 'GroupControl::k_SIZE' elements of the entry range.
3976 //
3977 // It may be surprising that the size of these ranges is not always a
3978 // multiple of 'GroupControl::k_SIZE' despite the fact that the capacity of
3979 // a 'FlatHashTable' is always a power of 2. However, this operation can
3980 // be invoked midway through copying one entry array to another if copying
3981 // an entry throws and the already-copied elements need to then be
3982 // destroyed as part of cleaning up during exception handling.
3983
3984 static_cast<void>(lastControl); // silence unused variable warnings
3985
3986 const bsl::size_t numEntries =
3987 static_cast<bsl::size_t>(bsl::distance(firstEntry, lastEntry));
3988 const bsl::size_t numGroupedEntries =
3989 numEntries - (numEntries % GroupControl::k_SIZE);
3990
3991 for (bsl::size_t idx = 0;
3992 idx != numGroupedEntries;
3993 idx += GroupControl::k_SIZE) {
3994 GroupControl groupControl(firstControl + idx);
3995 bsl::uint32_t candidates = groupControl.inUse();
3996 while (candidates) {
3997 const int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
3998 bslma::DestructionUtil::destroy(firstEntry + idx + offset);
3999 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
4000 }
4001 }
4002
4003 for (bsl::size_t idx = numGroupedEntries; idx != numEntries; ++idx) {
4004 ENTRY_TYPE& entry = *(firstEntry + idx);
4005 const bsl::uint8_t& control = *(firstControl + idx);
4006
4007 if (0 == (control & GroupControl::k_EMPTY)) {
4008 bslma::DestructionUtil::destroy(&entry);
4009 }
4010 }
4011}
4012
4013template <class ENTRY_TYPE>
4014inline
4015void FlatHashTable_ImplUtil::destroyEntryArray(
4016 ENTRY_TYPE *,
4017 ENTRY_TYPE *,
4018 const bsl::uint8_t *,
4019 const bsl::uint8_t *,
4020 bsl::true_type triviallyDestructible)
4021{
4022 (void) triviallyDestructible;
4023
4024 // Do nothing, in just the right way.
4025}
4026
4027// CLASS METHODS
4028template <class ENTRY_TYPE>
4029inline
4030void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
4031 ENTRY_TYPE *firstDestinationEntry,
4032 bsl::uint8_t *firstDestinationControl,
4033 const ENTRY_TYPE *firstSourceEntry,
4034 const ENTRY_TYPE *lastSourceEntry,
4035 const bsl::uint8_t *firstSourceControl,
4036 const bsl::uint8_t *lastSourceControl,
4037 bslma::Allocator *entryAllocator)
4038{
4039 BSLS_ASSERT_SAFE(bsl::distance(firstSourceEntry, lastSourceEntry) ==
4040 bsl::distance(firstSourceControl, lastSourceControl));
4041
4042 FlatHashTable_ImplUtil::copyEntryAndControlArrays(
4043 firstDestinationEntry,
4044 firstDestinationControl,
4045 firstSourceEntry,
4046 lastSourceEntry,
4047 firstSourceControl,
4048 lastSourceControl,
4049 entryAllocator,
4051}
4052
4053template <class ENTRY_TYPE>
4054inline
4055void FlatHashTable_ImplUtil::destroyEntryArray(
4056 ENTRY_TYPE *firstEntry,
4057 ENTRY_TYPE *lastEntry,
4058 const bsl::uint8_t *firstControl,
4059 const bsl::uint8_t *lastControl)
4060{
4061 BSLS_ASSERT_SAFE(bsl::distance(firstEntry, lastEntry) ==
4062 bsl::distance(firstControl, lastControl));
4063
4064 ///Implementation Note
4065 ///-------------------
4066 // If a type is trivially copyable then it is also trivially destructible.
4067 // The type trait 'bslmf::IsTriviallyCopyable' is available in C++03
4068 // mode and later, however 'bsl::is_trivially_destructible' is only
4069 // available in C++11 and later and not always on clang. So, this utility
4070 // 'struct' uses bitwise copyability as a stand-in for trivial
4071 // destructibility in order to provide certain optimizations uniformly
4072 // across all C++ versions.
4073
4075 IsEntryTypeTriviallyDestructible;
4076
4077 FlatHashTable_ImplUtil::destroyEntryArray(
4078 firstEntry,
4079 lastEntry,
4080 firstControl,
4081 lastControl,
4082 IsEntryTypeTriviallyDestructible());
4083}
4084
4085 // ------------------------------------------------------
4086 // class FlatHashTable_ImplUtil::DestroyEntryArrayProctor
4087 // ------------------------------------------------------
4088
4089// CREATORS
4090template <class ENTRY_TYPE>
4091inline
4092FlatHashTable_ImplUtil::DestroyEntryArrayProctor<
4093 ENTRY_TYPE>::DestroyEntryArrayProctor(ENTRY_TYPE *firstEntry,
4094 ENTRY_TYPE *lastEntry,
4095 const bsl::uint8_t *firstControl,
4096 const bsl::uint8_t *lastControl)
4097: d_firstEntry_p(firstEntry)
4098, d_lastEntry_p(lastEntry)
4099, d_firstControl_p(firstControl)
4100, d_lastControl_p(lastControl)
4101{
4102}
4103
4104template <class ENTRY_TYPE>
4105inline
4106FlatHashTable_ImplUtil::DestroyEntryArrayProctor<
4107 ENTRY_TYPE>::~DestroyEntryArrayProctor()
4108{
4109 ImplUtil::destroyEntryArray(d_firstEntry_p,
4110 d_lastEntry_p,
4111 d_firstControl_p,
4112 d_lastControl_p);
4113}
4114
4115// MANIPULATORS
4116template <class ENTRY_TYPE>
4117inline
4118void FlatHashTable_ImplUtil::DestroyEntryArrayProctor<ENTRY_TYPE>::moveEnd(
4119 bsl::ptrdiff_t offset)
4120{
4121 d_lastEntry_p += offset;
4122 d_lastControl_p += offset;
4123}
4124
4125template <class ENTRY_TYPE>
4126inline
4127void FlatHashTable_ImplUtil::DestroyEntryArrayProctor<ENTRY_TYPE>::release()
4128{
4129 d_firstEntry_p = 0;
4130 d_lastEntry_p = 0;
4131 d_firstControl_p = 0;
4132 d_lastControl_p = 0;
4133}
4134
4135} // close package namespace
4136
4137
4138#else // if ! defined(DEFINED_BDLC_FLATHASHTABLE_H)
4139# error Not valid except when included from bdlc_flathashtable.h
4140#endif // ! defined(COMPILING_BDLC_FLATHASHTABLE_H)
4141
4142#endif // ! defined(INCLUDED_BDLC_FLATHASHTABLE_CPP03)
4143
4144// ----------------------------------------------------------------------------
4145// Copyright 2020 Bloomberg Finance L.P.
4146// Copyright 2018 The Abseil Authors
4147//
4148// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4149// use this file except in compliance with the License. You may obtain a copy
4150// of the License at
4151//
4152// http://www.apache.org/licenses/LICENSE-2.0
4153//
4154// Unless required by applicable law or agreed to in writing, software
4155// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4156// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4157// License for the specific language governing permissions and limitations
4158// under the License.
4159// ----------------------------- END-OF-FILE ----------------------------------
4160
4161/** @} */
4162/** @} */
4163/** @} */
static const bsl::uint8_t k_EMPTY
Definition bdlc_flathashtable_groupcontrol.h:124
static const bsl::size_t k_SIZE
Definition bdlc_flathashtable_groupcontrol.h:126
FlatHashTable_IteratorImp & operator=(const FlatHashTable_IteratorImp &rhs)
Definition bdlc_flathashtable.h:1082
FlatHashTable_IteratorImp()
Definition bdlc_flathashtable.h:1050
void operator++()
Definition bdlc_flathashtable.h:1094
ENTRY & operator*() const
Definition bdlc_flathashtable.h:1115
Definition bdlc_flathashtable.h:317
void clear()
Definition bdlc_flathashtable.h:1580
bsl::size_t erase(const KEY &key)
Definition bdlc_flathashtable.h:1632
const ENTRY * entries() const
Definition bdlc_flathashtable.h:1981
static const bsl::size_t k_MIN_CAPACITY
Definition bdlc_flathashtable.h:398
float max_load_factor() const
Definition bdlc_flathashtable.h:2056
const_iterator cbegin() const
Definition bdlc_flathashtable.h:2092
void swap(FlatHashTable &other)
Definition bdlc_flathashtable.h:1918
HASH hash_type
Definition bdlc_flathashtable.h:328
EQUAL key_equal_type
Definition bdlc_flathashtable.h:329
static const bsl::size_t k_MAX_LOAD_FACTOR_NUMERATOR
Definition bdlc_flathashtable.h:403
void reset()
Definition bdlc_flathashtable.h:1806
bsl::pair< iterator, bool > emplace(ARGS &&... args)
iterator find(const KEY &key)
Definition bdlc_flathashtable.h:1741
iterator end()
Definition bdlc_flathashtable.h:1909
bool empty() const
Definition bdlc_flathashtable.h:1970
bsl::pair< iterator, bool > try_emplace(const KEY &key, ARGS &&... args)
static const bsl::size_t k_MAX_LOAD_FACTOR_DENOMINATOR
Definition bdlc_flathashtable.h:408
ENTRY_UTIL entry_util_type
Definition bdlc_flathashtable.h:327
static const bsl::int8_t k_HASHLET_MASK
Definition bdlc_flathashtable.h:401
bsl::enable_if< bsl::is_convertible< ENTRY_TYPE, ENTRY >::value, bsl::pair< iterator, bool > >::type insert(BSLS_COMPILERFEATURES_FORWARD_REF(ENTRY_TYPE) entry)
Definition bdlc_flathashtable.h:564
bslma::Allocator * allocator() const
Return the allocator used by this hash table to supply memory.
Definition bdlc_flathashtable.h:2118
bsl::size_t capacity() const
Definition bdlc_flathashtable.h:1936
bslstl::ForwardIterator< const ENTRY, IteratorImp > const_iterator
Definition bdlc_flathashtable.h:334
bslstl::ForwardIterator< ENTRY, IteratorImp > iterator
Definition bdlc_flathashtable.h:332
const bsl::uint8_t * controls() const
Definition bdlc_flathashtable.h:1955
ENTRY entry_type
Definition bdlc_flathashtable.h:326
ENTRY & operator[](BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) key)
Definition bdlc_flathashtable.h:1557
KEY key_type
Definition bdlc_flathashtable.h:325
EQUAL key_eq() const
Definition bdlc_flathashtable.h:2032
bool contains(const KEY &key) const
Definition bdlc_flathashtable.h:1943
iterator begin()
Definition bdlc_flathashtable.h:1892
void reserve(bsl::size_t numEntries)
Definition bdlc_flathashtable.h:1787
const_iterator cend() const
Definition bdlc_flathashtable.h:2100
bsl::size_t size() const
Return the number of entries in this table.
Definition bdlc_flathashtable.h:2064
bsl::size_t count(const KEY &key) const
Definition bdlc_flathashtable.h:1962
FlatHashTable & operator=(const FlatHashTable &rhs)
Definition bdlc_flathashtable.h:1529
~FlatHashTable()
Destroy this object and each of its entries.
Definition bdlc_flathashtable.h:1505
HASH hash_function() const
Definition bdlc_flathashtable.h:2025
float load_factor() const
Definition bdlc_flathashtable.h:2043
void rehash(bsl::size_t minimumCapacity)
Definition bdlc_flathashtable.h:1766
bsl::pair< iterator, iterator > equal_range(const KEY &key)
Definition bdlc_flathashtable.h:1599
Definition bslstl_pair.h:1210
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:194
Definition bslma_allocator.h:457
virtual void deallocate(void *address)=0
virtual void * allocate(size_type size)=0
Definition bslma_deallocatorproctor.h:312
Definition bslma_destructorguard.h:132
Definition bslma_destructorproctor.h:259
Definition bslmf_movableref.h:751
Definition bslstl_forwarditerator.h:169
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_ASSERT_OPT(X)
Definition bsls_assert.h:1856
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_PERFORMANCEHINT_PREDICT_LIKELY(expr)
Definition bsls_performancehint.h:451
bool operator!=(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
bool operator==(const FileCleanerConfiguration &lhs, const FileCleanerConfiguration &rhs)
void swap(OptionValue &a, OptionValue &b)
Definition bdlc_bitarray.h:503
void swap(BitArray &a, BitArray &b)
bool operator==(const BitArray &lhs, const BitArray &rhs)
bool operator!=(const BitArray &lhs, const BitArray &rhs)
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4126
T::iterator begin(T &container)
Definition bslstl_iterator.h:1495
T::iterator end(T &container)
Definition bslstl_iterator.h:1523
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
static int numTrailingUnsetBits(unsigned int value)
Definition bdlb_bitutil.h:462
static unsigned int withBitCleared(unsigned int value, int index)
Definition bdlb_bitutil.h:581
static int log2(unsigned int value)
Definition bdlb_bitutil.h:338
static unsigned int roundUpToBinaryPower(unsigned int value)
Definition bdlb_bitutil.h:550
Definition bslmf_enableif.h:525
Definition bslmf_integralconstant.h:244
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
static void destructiveMove(TARGET_TYPE *address, const ALLOCATOR &allocator, TARGET_TYPE *original)
Definition bslma_constructionutil.h:1295
Definition bslmf_isbitwisecopyable.h:298
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060
Definition bsls_objectbuffer.h:276
TYPE * address()
Definition bsls_objectbuffer.h:334
TYPE & object()
Definition bsls_objectbuffer.h:351