BDE 4.39.x 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 Thu Mar 5 22:51:43 2026
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 `additionalLength` values.
110 ///
111 /// \pre The behavior is undefined unless
112 /// `entries` points to at least `1 + additionalLength` entry values and
113 /// `controls` points to at least
114 /// `1 + additionalLength + ControlGroup::k_SIZE` control values.
115 FlatHashTable_IteratorImp(ENTRY *entries,
116 const bsl::uint8_t *controls,
117 bsl::size_t additionalLength);
118
119 /// Create a `FlatHashTable_IteratorImp` having the same value as the
120 /// specified `original`.
122
123 ~FlatHashTable_IteratorImp() = default;
124 // Destroy this object.
125
126 // MANIPULATORS
127
128 /// Assign to this `FlatHashTable_IteratorImp` the value of the
129 /// specified `rhs`.
131
132 /// Advance the `FlatHashTable_IteratorImp` to the next present element
133 /// in the underlying flat hash table. If there is no such element,
134 /// assign this object to `FlatHashTable_InteratorImp()`.
135 ///
136 /// \pre The behavior is undefined unless this `FlatHashTable_IteratorImp` refers to a
137 /// valid element of the underlying sequence.
138 void operator++();
139
140 // ACCESSORS
141
142 /// Return a reference to the element referred to by this `FlatHashTable_IteratorImp`.
143 ///
144 /// \pre The behavior is undefined unless this
145 /// `FlatHashTable_IteratorImp() != *this`.
146 ENTRY& operator*() const;
147};
148
149// FREE OPERATORS
150
151/// Return true if the specified `a` and `b` are equal. Two
152/// `FlatHashTable_IteratorImp` objects are equal if they both refer to the
153/// same element of the underlying flat hash table, or are both not dereferenceable.
154///
155/// \pre The behavior is undefined unless `a` and `b` refer to
156/// the same `FlatHashTable`.
157template <class ENTRY>
158bool operator==(const FlatHashTable_IteratorImp<ENTRY>& a,
159 const FlatHashTable_IteratorImp<ENTRY>& b);
160
161 // ===================
162 // class FlatHashTable
163 // ===================
164
165/// This class template provides a flat hash table implementation useful for
166/// implementing a flat hash set and flat hash map.
167template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
168class FlatHashTable
169{
170 // PRIVATE TYPES
171 typedef FlatHashTable_GroupControl GroupControl;
172 typedef FlatHashTable_ImplUtil ImplUtil;
173 typedef FlatHashTable_IteratorImp<ENTRY> IteratorImp;
174
175 public:
176 // TYPES
177 typedef KEY key_type;
178 typedef ENTRY entry_type;
179 typedef ENTRY_UTIL entry_util_type;
180 typedef HASH hash_type;
181 typedef EQUAL key_equal_type;
182
183 typedef typename bslstl::ForwardIterator<ENTRY,
184 IteratorImp> iterator;
185 typedef typename bslstl::ForwardIterator<const ENTRY,
186 IteratorImp> const_iterator;
187
188 private:
189 // DATA
190 ENTRY *d_entries_p; // entries of this table
191 bsl::uint8_t *d_controls_p; // control values of this table
192 bsl::size_t d_size; // number of active values
193 bsl::size_t d_capacity; // size of values array
194 int d_groupControlShift; // number of bits to shift hash
195 HASH d_hasher; // hashing functor
196 EQUAL d_equal; // equality functor
197 bslma::Allocator *d_allocator_p; // allocator
198
199 // PRIVATE CLASS METHODS
200
201 /// Return the index of the first available entry indicated by the
202 /// specified `controls` at or after the specified `index`, assuming
203 /// `controls` has the specified `capacity`.
204 ///
205 /// \pre The behavior is undefined unless `index < capacity` and `controls` has at least `capacity`
206 /// entries.
207 static bsl::size_t findAvailable(bsl::uint8_t *controls,
208 bsl::size_t index,
209 bsl::size_t capacity);
210
211 // PRIVATE MANIPULATORS
212
213 /// Load `true` into the specified `notFound` if there is no entry in
214 /// this table having the specified `key` with the specified
215 /// `hashValue`, and `false` otherwise. Return the index of the entry
216 /// within `d_entries_p` which contains the `key` if such an entry
217 /// exists, otherwise insert an entry with value obtained from
218 /// `ENTRY_UTIL::construct` and return the index of this entry. This
219 /// method rehashes the table if the `key` was not present and the
220 /// addition of an entry would cause the load factor to exceed `max_load_factor()`.
221 ///
222 /// \pre The behavior is undefined unless
223 /// `hashValue == d_hasher(key)`.
224 bsl::size_t indexOfKey(bool *notFound,
225 const KEY& key,
226 bsl::size_t hashValue);
227
228 /// Load `true` into the specified `notFound` if there is no entry in
229 /// this table equvalent to the specified `key` with the specified
230 /// `hashValue`, and `false` otherwise. Return the index of the entry
231 /// within `d_entries_p` which contains the `key` if such an entry
232 /// exists, otherwise insert an entry with value obtained from
233 /// `ENTRY_UTIL::construct` and return the index of this entry. This
234 /// method rehashes the table if the `key` was not present and the
235 /// addition of an entry would cause the load factor to exceed `max_load_factor()`.
236 ///
237 /// \pre The behavior is undefined unless
238 /// `hashValue == d_hasher(key)`.
239 template <class LOOKUP_KEY>
240 typename bsl::enable_if<
241 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
242 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
243 , bsl::size_t>::type
244 indexOfKeyTransparent(bool *notFound,
245 const LOOKUP_KEY& key,
246 bsl::size_t hashValue)
247 {
248 BSLS_ASSERT_SAFE(hashValue == d_hasher(key));
249
250 bsl::size_t index = findTransparentKey(key, hashValue);
251
252 if (index == d_capacity) {
253 *notFound = true;
254
255 if (d_size >= k_MAX_LOAD_FACTOR_NUMERATOR
256 * (d_capacity / k_MAX_LOAD_FACTOR_DENOMINATOR)) {
257 rehashRaw(d_capacity > 0 ? 2 * d_capacity : k_MIN_CAPACITY);
258 }
259
260 index = (hashValue >> d_groupControlShift) * GroupControl::k_SIZE;
261 index = findAvailable(d_controls_p, index, d_capacity);
262 }
263 else {
264 *notFound = false;
265 }
266
267 return index;
268 }
269
270 /// Change the capacity of this table to the specified `newCapacity`,
271 /// and redistribute all the contained elements into the new sequence of
272 /// entries, according to their hash values.
273 ///
274 /// \pre The behavior is undefined unless `0 < newCapacity` and `newCapacity` satisfies all class
275 /// invariants.
276 void rehashRaw(bsl::size_t newCapacity);
277
278 // PRIVATE ACCESSORS
279
280 /// Return the index of the entry within `d_entries_p` containing the
281 /// specified `key`, which has the specified `hashValue`, or
282 /// `d_capacity` if the `key` is not present.
283 ///
284 /// \pre The behavior is undefined unless `hashValue == d_hasher(key)`.
285 bsl::size_t findKey(const KEY& key, bsl::size_t hashValue) const;
286
287 /// Return the index of the entry within `d_entries_p` containing a key
288 /// equivalent to the specified `key`, which has the specified `hashValue`,
289 /// or `d_capacity` if a key equivalent to `key` is not present.
290 ///
291 /// \pre The behavior is undefined unless `hashValue == d_hasher(key)`.
292 template <class LOOKUP_KEY>
293 typename bsl::enable_if<
294 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
295 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
296 , bsl::size_t>::type
297 findTransparentKey(const LOOKUP_KEY& key, bsl::size_t hashValue) const
298 {
299 // Note: implemented inline due to Sun CC compilation error.
300
301 BSLS_ASSERT_SAFE(hashValue == d_hasher(key));
302
303 bsl::size_t index = (hashValue >> d_groupControlShift)
305 bsl::uint8_t hashlet = static_cast<bsl::uint8_t>(
306 hashValue & k_HASHLET_MASK);
307
308 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
309 bsl::uint8_t *controlStart = d_controls_p + index;
310 ENTRY *entryStart = d_entries_p + index;
311
312 GroupControl groupControl(controlStart);
313 bsl::uint32_t candidates = groupControl.match(hashlet);
314 while (candidates) {
315 int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
316
317 ENTRY *entry = entryStart + offset;
318
320 d_equal(ENTRY_UTIL::key(*entry), key))) {
321 return index + offset; // RETURN
322 }
323 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
324 }
325 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(groupControl.neverFull()))
326 {
327 break;
328 }
329
330 index = (index + GroupControl::k_SIZE) & (d_capacity - 1);
331 }
332
333 return d_capacity;
334 }
335
336 /// Return the minimum capacity that satisfies all class invariants, and
337 /// is at least the specified `minimumCapacity`.
338 bsl::size_t minimumCompliantCapacity(bsl::size_t minimumCapacity) const;
339
340 private:
341 // NOT IMPLEMENTED
342 FlatHashTable();
343
344 public:
345 // PUBLIC CLASS DATA
346 static const bsl::size_t k_MIN_CAPACITY = 2 * GroupControl::k_SIZE;
347 // min. non-zero capacity
348
349 static const bsl::int8_t k_HASHLET_MASK = 0x7f; // hashlet = hash & MASK
350
351 static const bsl::size_t k_MAX_LOAD_FACTOR_NUMERATOR = 7;
352 // numerator of fraction
353 // that specifies the
354 // maximum load factor
355
356 static const bsl::size_t k_MAX_LOAD_FACTOR_DENOMINATOR = 8;
357 // denominator of
358 // fraction that
359 // specifies the maximum
360 // load factor
361
362 // CREATORS
363
364 /// Create an empty table having at least the specified `capacity`, that
365 /// will use the specified `hash` to generate hash values for the keys
366 /// of the entries contained in this table, and the specified `equal` to
367 /// verify that the keys of the two entries are the same. Optionally
368 /// specify a `basicAllocator` used to supply memory. If
369 /// `basicAllocator` is 0, the currently installed default allocator is
370 /// used. If `0 == capacity`, no memory is allocated and the object is
371 /// defined to be in the "zero-capacity" state.
372 FlatHashTable(bsl::size_t capacity,
373 const HASH& hash,
374 const EQUAL& equal,
375 bslma::Allocator *basicAllocator = 0);
376
377 /// Create a table having the same value, hasher, and key-equality
378 /// comparator as the specified `original`. Optionally specify a
379 /// `basicAllocator` used to supply memory. If `basicAllocator` is 0,
380 /// the currently installed default allocator is used.
381 FlatHashTable(const FlatHashTable& original,
382 bslma::Allocator *basicAllocator = 0);
383
384 /// Create an table having the same value as the specified `original`
385 /// object by moving (in constant time) the contents of `original` to
386 /// the new table. Use a copy of `original.hash_function()` to generate
387 /// hash values for the keys of the entries contained in this table.
388 /// Use a copy of `original.key_eq()` to verify that two keys are equal.
389 /// The allocator associated with `original` is propagated for use in
390 /// the newly-created table. `original` is left in a (valid)
391 /// unspecified state.
392 explicit FlatHashTable(bslmf::MovableRef<FlatHashTable> original);
393
394 /// Create a table having the same value, hasher, and key-equality
395 /// comparator as the specified `original` object by moving the contents
396 /// of `original` to the new table, and using the specified
397 /// `basicAllocator` to supply memory. Use a copy of
398 /// `original.hash_function()` to generate hash values for the entries
399 /// contained in this table. Use a copy of `original.key_eq()` to
400 /// verify that the keys of two entries are equal. This method requires
401 /// that the (template parameter) type `ENTRY` be `move-insertable` into
402 /// this `FlatHashTable`. If `basicAllocator` is 0, the currently
403 /// installed default allocator is used. If `original` and the newly
404 /// created object have the same allocator then the value of `original`
405 /// becomes unspecified but valid, and no exceptions will be thrown;
406 /// otherwise `original` is unchanged (and an exception may be thrown).
407 FlatHashTable(bslmf::MovableRef<FlatHashTable> original,
408 bslma::Allocator *basicAllocator);
409
410 /// Destroy this object and each of its entries.
412
413 // MANIPULATORS
414
415 /// Assign to this object the value, hasher, and key-equality functor of
416 /// the specified `rhs` object and return a reference offering
417 /// modifiable access to this object.
418 FlatHashTable& operator=(const FlatHashTable& rhs);
419
420 /// Assign to this object the value, hash function, and key-equality
421 /// comparator of the specified `rhs` object and return a reference
422 /// offering modifiable access to this object. The entries of `rhs` are
423 /// moved (in constant time) to this object if the two have the same
424 /// allocator, otherwise entries from `rhs` are moved into this table.
425 /// In either case, `rhs` is left in a valid but unspecified state. If
426 /// an exception is thrown, this object is left in a valid but
427 /// unspecified state.
429
430 /// If an entry with the specified `key` is not already present in this
431 /// table, insert an entry having the value defined by
432 /// `ENTRY_UTIL::construct`; otherwise, this method has no effect.
433 /// Return an iterator referring to the (possibly newly inserted) object
434 /// in this table with the `key`.
435 template <class KEY_TYPE>
436 ENTRY& operator[](BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) key);
437
438 /// Remove all entries from this table.
439 /// \note Note that this table will be
440 /// empty after calling this method, but allocated memory may be
441 /// retained for future use. See the `capacity` method.
442 void clear();
443
444 /// Return a pair of iterators providing modifiable access to the
445 /// sequence of objects in this flat hash table having the specified
446 /// `key`, where the first iterator is positioned at the start of the
447 /// sequence, and the second is positioned one past the end of the
448 /// sequence. If this table contains no object having `key`, then the
449 /// two returned iterators will have the same value, `end()`.
450 ///
451 /// \note Note that since each key in a flat hash table is unique, the returned range
452 /// contains at most one element.
454
455 /// Return a pair of iterators providing non-modifiable access to the
456 /// sequence of objects in this table having a key equivalent to the
457 /// specified `key`, where the first iterator is positioned at the start
458 /// of the sequence, and the second is positioned one past the end of the
459 /// sequence. If this table contains no objects having a key equivalent to
460 /// the specified `key`, then the two returned iterators will have the same value, `end()`.
461 ///
462 /// \note Note that since a table maintains unique keys, the
463 /// range will contain at most one entry.
464 template <class LOOKUP_KEY>
465 typename bsl::enable_if<
466 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
467 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
469 equal_range(const LOOKUP_KEY& key)
470 {
471 // Note: implemented inline due to Sun CC compilation error.
472
473 iterator it1 = find(key);
474 iterator it2 = it1;
475 if (it1 != end()) {
476 ++it2;
477 }
478 return bsl::make_pair(it1, it2);
479 }
480
481#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
482// {{{ BEGIN GENERATED CODE
483// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
484#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
485#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
486#endif
487#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A
488#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A BDLC_FLATHASHTABLE_VARIADIC_LIMIT
489#endif
490#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 0
492 );
493#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 0
494
495#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 1
496 template< class ARGS_01>
498 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01);
499#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 1
500
501#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 2
502 template< class ARGS_01,
503 class ARGS_02>
505 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
506 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02);
507#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 2
508
509#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 3
510 template< class ARGS_01,
511 class ARGS_02,
512 class ARGS_03>
514 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
515 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
516 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03);
517#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 3
518
519#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 4
520 template< class ARGS_01,
521 class ARGS_02,
522 class ARGS_03,
523 class ARGS_04>
525 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
526 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
527 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
528 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04);
529#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 4
530
531#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 5
532 template< class ARGS_01,
533 class ARGS_02,
534 class ARGS_03,
535 class ARGS_04,
536 class ARGS_05>
538 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
539 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
540 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
541 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
542 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05);
543#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 5
544
545#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 6
546 template< class ARGS_01,
547 class ARGS_02,
548 class ARGS_03,
549 class ARGS_04,
550 class ARGS_05,
551 class ARGS_06>
553 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
554 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
555 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
556 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
557 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
558 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06);
559#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 6
560
561#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 7
562 template< class ARGS_01,
563 class ARGS_02,
564 class ARGS_03,
565 class ARGS_04,
566 class ARGS_05,
567 class ARGS_06,
568 class ARGS_07>
570 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
571 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
572 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
573 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
574 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
575 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
576 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07);
577#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 7
578
579#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 8
580 template< class ARGS_01,
581 class ARGS_02,
582 class ARGS_03,
583 class ARGS_04,
584 class ARGS_05,
585 class ARGS_06,
586 class ARGS_07,
587 class ARGS_08>
589 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
590 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
591 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
592 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
593 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
594 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
595 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
596 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08);
597#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 8
598
599#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 9
600 template< class ARGS_01,
601 class ARGS_02,
602 class ARGS_03,
603 class ARGS_04,
604 class ARGS_05,
605 class ARGS_06,
606 class ARGS_07,
607 class ARGS_08,
608 class ARGS_09>
610 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
611 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
612 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
613 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
614 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
615 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
616 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
617 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
618 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09);
619#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 9
620
621#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 10
622 template< class ARGS_01,
623 class ARGS_02,
624 class ARGS_03,
625 class ARGS_04,
626 class ARGS_05,
627 class ARGS_06,
628 class ARGS_07,
629 class ARGS_08,
630 class ARGS_09,
631 class ARGS_10>
633 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
634 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
635 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
636 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
637 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
638 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
639 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
640 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
641 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
642 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10);
643#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_A >= 10
644
645#else
646// The generated code below is a workaround for the absence of perfect
647// forwarding in some compilers.
648 template< class... ARGS>
651// }}} END GENERATED CODE
652#endif
653
654 /// Remove from this table the object having the specified `key`, if it
655 /// exists, and return 1; otherwise (there is no object with a key equal
656 /// to `key` in this table) return 0 with no other effect. This method
657 /// invalidates all iterators, and references to the removed element.
658 bsl::size_t erase(const KEY& key);
659
660// {{{ BEGIN GENERATED CODE
661// The generated code below is a workaround for the absence of perfect
662// forwarding in some compilers.
663 template <class LOOKUP_KEY>
664 typename bsl::enable_if<
665 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
666 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
667 , bsl::size_t>::type
669 {
670
671 iterator it = find(key);
672 if (it == end()) {
673 return 0;
674 }
675 erase(it);
676 return 1;
677 }
678// }}} END GENERATED CODE
679
680 /// Remove from this table the object at the specified `position`, and
681 /// return an iterator referring to the element immediately following
682 /// the removed element, or to the past-the-end position if the removed
683 /// element was the last element in the sequence of elements maintained
684 /// by this table. This method invalidates all iterators, and references to the removed element.
685 ///
686 /// \pre The behavior is undefined unless
687 /// `position` refers to an object in this table.
688 iterator erase(const_iterator position);
689 iterator erase(iterator position);
690
691 /// Remove from this table the objects starting at the specified `first`
692 /// position up to, but not including, the specified `last` position,
693 /// and return `last`. This method invalidates all iterators, and references to the removed element.
694 ///
695 /// \pre The behavior is undefined unless
696 /// `first` and `last` either refer to elements in this table or are the
697 /// `end` iterator, and the `first` position is at or before the `last`
698 /// position in the iteration sequence provided by this container.
700
701 /// Return an iterator providing modifiable access to the object in this
702 /// flat hash table with a key equal to the specified `key`, if such an
703 /// entry exists, and `end()` otherwise.
704 iterator find(const KEY& key);
705
706 /// Return an iterator providing modifiable access to the object in this
707 /// flat hash table with a key equivalent to the specified `key`, if such
708 /// an entry exists, and `end()` otherwise.
709 template <class LOOKUP_KEY>
710 typename bsl::enable_if<
711 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
712 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
713 , iterator>::type
714 find(const LOOKUP_KEY& key)
715 {
716 // Note: implemented inline due to Sun CC compilation error.
717
718 bsl::size_t index = findTransparentKey(key, d_hasher(key));
719 if (index < d_capacity) {
720 return iterator(IteratorImp(d_entries_p + index,
721 d_controls_p + index,
722 d_capacity - index - 1)); // RETURN
723 }
724 return end();
725 }
726
727 /// Insert the specified `entry` into this table if the key of the
728 /// `entry` does not already exist in this table; otherwise, this method
729 /// has no effect. Return a `pair` whose `first` member is an iterator
730 /// referring to the (possibly newly inserted) object in this table
731 /// whose key is the equal to that of the object to be inserted, and
732 /// whose `second` member is `true` if a new entry was inserted, and
733 /// `false` if a entry having an equal key was already present. Bitwise
734 /// movable types that are not bitwise copyable will be copied (to avoid
735 /// confusion with regard to calling the `entry` destructor after this
736 /// call).
737 bsl::pair<iterator, bool> insert(const ENTRY &entry);
739
740// {{{ BEGIN GENERATED CODE
741// The generated code below is a workaround for the absence of perfect
742// forwarding in some compilers.
743 template <class LOOKUP_KEY>
744 typename bsl::enable_if<
745 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
746 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
749 {
750
751 bool notFound;
752 bsl::size_t hashValue = d_hasher(key);
753 bsl::size_t index = indexOfKeyTransparent(&notFound,
754 key,
755 hashValue);
756
757 if (notFound) {
758 ENTRY_UTIL::construct(
759 d_entries_p + index,
760 d_allocator_p,
761 BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key));
762
763 d_controls_p[index] = static_cast<bsl::uint8_t>(
764 hashValue & k_HASHLET_MASK);
765
766 ++d_size;
767 }
768
769 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
770 d_controls_p + index,
771 d_capacity - index - 1),
772 notFound);
773 }
774// }}} END GENERATED CODE
775
776 /// Create an object for each iterator in the range starting at the
777 /// specified `first` iterator and ending immediately before the
778 /// specified `last` iterator, by converting from the object referred to
779 /// by each iterator. Insert into this table each such object whose key
780 /// is not already contained. The (template parameter) type
781 /// `INPUT_ITERATOR` shall meet the requirements of an input iterator
782 /// defined in the C++11 standard [24.2.3] providing access to values of a type convertible to `ENTRY`.
783 ///
784 /// \pre The behavior is undefined unless
785 /// `first` and `last` refer to a sequence of valid values where `first`
786 /// is at a position at or before `last`.
787 template <class INPUT_ITERATOR>
788 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
789
790 /// Change the capacity of this table to at least the specified
791 /// `minimumCapacity`, and redistribute all the contained elements into
792 /// a new sequence of entries, according to their hash values. If
793 /// `0 == minimumCapacity` and `0 == size()`, the table is returned to
794 /// the zero-capacity state. On return, `load_factor()` is less than or
795 /// equal to `max_load_factor()` and all iterators, pointers, and
796 /// references to elements of this `FlatHashTable` are invalidated.
797 void rehash(bsl::size_t minimumCapacity);
798
799 /// Change the capacity of this table to at least a capacity that can
800 /// accommodate the specified `numEntries` (accounting for the load
801 /// factor invariant), and redistribute all the contained elements into
802 /// a new sequence of entries, according to their hash values. If
803 /// `0 == numEntries` and `0 == size()`, the table is returned to the
804 /// zero-capacity state. After this call, `load_factor()` will be less than or equal to `max_load_factor()`.
805 ///
806 /// \note Note that this method is
807 /// effectively equivalent to:
808 /// @code
809 /// rehash(bsl::ceil(numEntries / max_load_factor()))
810 /// @endcode
811 void reserve(bsl::size_t numEntries);
812
813 /// Remove all entries from this table and release all memory from this
814 /// table, returning the table to the zero-capacity state.
815 void reset();
816
817#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
818// {{{ BEGIN GENERATED CODE
819// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
820#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
821#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
822#endif
823#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D
824#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D BDLC_FLATHASHTABLE_VARIADIC_LIMIT
825#endif
826#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
828#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
829
830#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
831 template< class ARGS_01>
833 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01);
834#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
835
836#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
837 template< class ARGS_01,
838 class ARGS_02>
840 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
841 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02);
842#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
843
844#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
845 template< class ARGS_01,
846 class ARGS_02,
847 class ARGS_03>
849 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
850 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
851 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03);
852#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
853
854#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
855 template< class ARGS_01,
856 class ARGS_02,
857 class ARGS_03,
858 class ARGS_04>
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#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
865
866#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
867 template< class ARGS_01,
868 class ARGS_02,
869 class ARGS_03,
870 class ARGS_04,
871 class ARGS_05>
873 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
874 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
875 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
876 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
877 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05);
878#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
879
880#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
881 template< class ARGS_01,
882 class ARGS_02,
883 class ARGS_03,
884 class ARGS_04,
885 class ARGS_05,
886 class ARGS_06>
888 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
889 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
890 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
891 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
892 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
893 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06);
894#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
895
896#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
897 template< class ARGS_01,
898 class ARGS_02,
899 class ARGS_03,
900 class ARGS_04,
901 class ARGS_05,
902 class ARGS_06,
903 class ARGS_07>
905 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
906 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
907 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
908 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
909 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
910 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
911 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07);
912#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
913
914#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
915 template< class ARGS_01,
916 class ARGS_02,
917 class ARGS_03,
918 class ARGS_04,
919 class ARGS_05,
920 class ARGS_06,
921 class ARGS_07,
922 class ARGS_08>
924 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
925 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
926 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
927 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
928 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
929 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
930 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
931 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08);
932#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
933
934#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
935 template< class ARGS_01,
936 class ARGS_02,
937 class ARGS_03,
938 class ARGS_04,
939 class ARGS_05,
940 class ARGS_06,
941 class ARGS_07,
942 class ARGS_08,
943 class ARGS_09>
945 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
946 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
947 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
948 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
949 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
950 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
951 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
952 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
953 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09);
954#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
955
956#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
957 template< class ARGS_01,
958 class ARGS_02,
959 class ARGS_03,
960 class ARGS_04,
961 class ARGS_05,
962 class ARGS_06,
963 class ARGS_07,
964 class ARGS_08,
965 class ARGS_09,
966 class ARGS_10>
968 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
969 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
970 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
971 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
972 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
973 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
974 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
975 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
976 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
977 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10);
978#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
979
980
981#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
983 BloombergLP::bslmf::MovableRef<KEY> key);
984#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
985
986#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
987 template <class ARGS_01>
989 BloombergLP::bslmf::MovableRef<KEY> key,
990 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01);
991#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
992
993#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
994 template <class ARGS_01,
995 class ARGS_02>
997 BloombergLP::bslmf::MovableRef<KEY> key,
998 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
999 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02);
1000#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
1001
1002#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
1003 template <class ARGS_01,
1004 class ARGS_02,
1005 class ARGS_03>
1007 BloombergLP::bslmf::MovableRef<KEY> key,
1008 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1009 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1010 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03);
1011#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
1012
1013#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
1014 template <class ARGS_01,
1015 class ARGS_02,
1016 class ARGS_03,
1017 class ARGS_04>
1019 BloombergLP::bslmf::MovableRef<KEY> key,
1020 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1021 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1022 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1023 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04);
1024#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
1025
1026#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
1027 template <class ARGS_01,
1028 class ARGS_02,
1029 class ARGS_03,
1030 class ARGS_04,
1031 class ARGS_05>
1033 BloombergLP::bslmf::MovableRef<KEY> key,
1034 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1035 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1036 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1037 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1038 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05);
1039#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
1040
1041#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
1042 template <class ARGS_01,
1043 class ARGS_02,
1044 class ARGS_03,
1045 class ARGS_04,
1046 class ARGS_05,
1047 class ARGS_06>
1049 BloombergLP::bslmf::MovableRef<KEY> key,
1050 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1051 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1052 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1053 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1054 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1055 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06);
1056#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
1057
1058#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
1059 template <class ARGS_01,
1060 class ARGS_02,
1061 class ARGS_03,
1062 class ARGS_04,
1063 class ARGS_05,
1064 class ARGS_06,
1065 class ARGS_07>
1067 BloombergLP::bslmf::MovableRef<KEY> key,
1068 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1069 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1070 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1071 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1072 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1073 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1074 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07);
1075#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
1076
1077#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
1078 template <class ARGS_01,
1079 class ARGS_02,
1080 class ARGS_03,
1081 class ARGS_04,
1082 class ARGS_05,
1083 class ARGS_06,
1084 class ARGS_07,
1085 class ARGS_08>
1087 BloombergLP::bslmf::MovableRef<KEY> key,
1088 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1089 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1090 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1091 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1092 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1093 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1094 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
1095 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08);
1096#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
1097
1098#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
1099 template <class ARGS_01,
1100 class ARGS_02,
1101 class ARGS_03,
1102 class ARGS_04,
1103 class ARGS_05,
1104 class ARGS_06,
1105 class ARGS_07,
1106 class ARGS_08,
1107 class ARGS_09>
1109 BloombergLP::bslmf::MovableRef<KEY> key,
1110 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1111 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1112 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1113 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1114 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1115 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1116 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
1117 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
1118 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09);
1119#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
1120
1121#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
1122 template <class ARGS_01,
1123 class ARGS_02,
1124 class ARGS_03,
1125 class ARGS_04,
1126 class ARGS_05,
1127 class ARGS_06,
1128 class ARGS_07,
1129 class ARGS_08,
1130 class ARGS_09,
1131 class ARGS_10>
1133 BloombergLP::bslmf::MovableRef<KEY> key,
1134 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1135 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1136 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1137 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1138 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1139 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1140 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
1141 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
1142 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
1143 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10);
1144#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
1145
1146
1147#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
1148 template <class LOOKUP_KEY>
1149 typename bsl::enable_if<
1150 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1151 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1154 {
1155 bool notFound;
1156 bsl::size_t hashValue = d_hasher(key);
1157 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1158
1159 if (notFound) {
1160 ENTRY_UTIL::construct(d_entries_p + index,
1161 d_allocator_p);
1162
1163 d_controls_p[index] = static_cast<bsl::uint8_t>(
1164 hashValue & k_HASHLET_MASK);
1165 ++d_size;
1166 }
1167
1168 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1169 d_controls_p + index,
1170 d_capacity - index - 1),
1171 notFound);
1172 }
1173#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 0
1174
1175#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
1176 template <class LOOKUP_KEY, class ARGS_01>
1177 typename bsl::enable_if<
1178 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1179 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1182 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
1183 {
1184 bool notFound;
1185 bsl::size_t hashValue = d_hasher(key);
1186 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1187
1188 if (notFound) {
1189 ENTRY_UTIL::construct(d_entries_p + index,
1190 d_allocator_p,
1191 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
1192
1193 d_controls_p[index] = static_cast<bsl::uint8_t>(
1194 hashValue & k_HASHLET_MASK);
1195 ++d_size;
1196 }
1197
1198 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1199 d_controls_p + index,
1200 d_capacity - index - 1),
1201 notFound);
1202 }
1203#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 1
1204
1205#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
1206 template <class LOOKUP_KEY, class ARGS_01,
1207 class ARGS_02>
1208 typename bsl::enable_if<
1209 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1210 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1213 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1214 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
1215 {
1216 bool notFound;
1217 bsl::size_t hashValue = d_hasher(key);
1218 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1219
1220 if (notFound) {
1221 ENTRY_UTIL::construct(d_entries_p + index,
1222 d_allocator_p,
1223 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1224 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
1225
1226 d_controls_p[index] = static_cast<bsl::uint8_t>(
1227 hashValue & k_HASHLET_MASK);
1228 ++d_size;
1229 }
1230
1231 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1232 d_controls_p + index,
1233 d_capacity - index - 1),
1234 notFound);
1235 }
1236#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 2
1237
1238#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
1239 template <class LOOKUP_KEY, class ARGS_01,
1240 class ARGS_02,
1241 class ARGS_03>
1242 typename bsl::enable_if<
1243 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1244 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1247 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1248 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1249 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
1250 {
1251 bool notFound;
1252 bsl::size_t hashValue = d_hasher(key);
1253 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1254
1255 if (notFound) {
1256 ENTRY_UTIL::construct(d_entries_p + index,
1257 d_allocator_p,
1258 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1259 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1260 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
1261
1262 d_controls_p[index] = static_cast<bsl::uint8_t>(
1263 hashValue & k_HASHLET_MASK);
1264 ++d_size;
1265 }
1266
1267 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1268 d_controls_p + index,
1269 d_capacity - index - 1),
1270 notFound);
1271 }
1272#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 3
1273
1274#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
1275 template <class LOOKUP_KEY, class ARGS_01,
1276 class ARGS_02,
1277 class ARGS_03,
1278 class ARGS_04>
1279 typename bsl::enable_if<
1280 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1281 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1284 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1285 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1286 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1287 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
1288 {
1289 bool notFound;
1290 bsl::size_t hashValue = d_hasher(key);
1291 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1292
1293 if (notFound) {
1294 ENTRY_UTIL::construct(d_entries_p + index,
1295 d_allocator_p,
1296 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1297 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1298 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1299 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
1300
1301 d_controls_p[index] = static_cast<bsl::uint8_t>(
1302 hashValue & k_HASHLET_MASK);
1303 ++d_size;
1304 }
1305
1306 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1307 d_controls_p + index,
1308 d_capacity - index - 1),
1309 notFound);
1310 }
1311#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 4
1312
1313#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
1314 template <class LOOKUP_KEY, class ARGS_01,
1315 class ARGS_02,
1316 class ARGS_03,
1317 class ARGS_04,
1318 class ARGS_05>
1319 typename bsl::enable_if<
1320 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1321 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1324 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1325 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1326 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1327 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1328 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
1329 {
1330 bool notFound;
1331 bsl::size_t hashValue = d_hasher(key);
1332 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1333
1334 if (notFound) {
1335 ENTRY_UTIL::construct(d_entries_p + index,
1336 d_allocator_p,
1337 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1338 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1339 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1340 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
1341 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05));
1342
1343 d_controls_p[index] = static_cast<bsl::uint8_t>(
1344 hashValue & k_HASHLET_MASK);
1345 ++d_size;
1346 }
1347
1348 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1349 d_controls_p + index,
1350 d_capacity - index - 1),
1351 notFound);
1352 }
1353#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 5
1354
1355#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
1356 template <class LOOKUP_KEY, class ARGS_01,
1357 class ARGS_02,
1358 class ARGS_03,
1359 class ARGS_04,
1360 class ARGS_05,
1361 class ARGS_06>
1362 typename bsl::enable_if<
1363 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1364 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1367 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1368 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1369 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1370 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1371 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1372 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
1373 {
1374 bool notFound;
1375 bsl::size_t hashValue = d_hasher(key);
1376 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1377
1378 if (notFound) {
1379 ENTRY_UTIL::construct(d_entries_p + index,
1380 d_allocator_p,
1381 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1382 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1383 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1384 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
1385 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
1386 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
1387
1388 d_controls_p[index] = static_cast<bsl::uint8_t>(
1389 hashValue & k_HASHLET_MASK);
1390 ++d_size;
1391 }
1392
1393 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1394 d_controls_p + index,
1395 d_capacity - index - 1),
1396 notFound);
1397 }
1398#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 6
1399
1400#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
1401 template <class LOOKUP_KEY, class ARGS_01,
1402 class ARGS_02,
1403 class ARGS_03,
1404 class ARGS_04,
1405 class ARGS_05,
1406 class ARGS_06,
1407 class ARGS_07>
1408 typename bsl::enable_if<
1409 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1410 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1413 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1414 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1415 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1416 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1417 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1418 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1419 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
1420 {
1421 bool notFound;
1422 bsl::size_t hashValue = d_hasher(key);
1423 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1424
1425 if (notFound) {
1426 ENTRY_UTIL::construct(d_entries_p + index,
1427 d_allocator_p,
1428 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1429 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1430 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1431 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
1432 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
1433 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
1434 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
1435
1436 d_controls_p[index] = static_cast<bsl::uint8_t>(
1437 hashValue & k_HASHLET_MASK);
1438 ++d_size;
1439 }
1440
1441 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1442 d_controls_p + index,
1443 d_capacity - index - 1),
1444 notFound);
1445 }
1446#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 7
1447
1448#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
1449 template <class LOOKUP_KEY, class ARGS_01,
1450 class ARGS_02,
1451 class ARGS_03,
1452 class ARGS_04,
1453 class ARGS_05,
1454 class ARGS_06,
1455 class ARGS_07,
1456 class ARGS_08>
1457 typename bsl::enable_if<
1458 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1459 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1462 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1463 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1464 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1465 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1466 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1467 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1468 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
1469 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
1470 {
1471 bool notFound;
1472 bsl::size_t hashValue = d_hasher(key);
1473 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1474
1475 if (notFound) {
1476 ENTRY_UTIL::construct(d_entries_p + index,
1477 d_allocator_p,
1478 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1479 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1480 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1481 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
1482 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
1483 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
1484 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
1485 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
1486
1487 d_controls_p[index] = static_cast<bsl::uint8_t>(
1488 hashValue & k_HASHLET_MASK);
1489 ++d_size;
1490 }
1491
1492 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1493 d_controls_p + index,
1494 d_capacity - index - 1),
1495 notFound);
1496 }
1497#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 8
1498
1499#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
1500 template <class LOOKUP_KEY, class ARGS_01,
1501 class ARGS_02,
1502 class ARGS_03,
1503 class ARGS_04,
1504 class ARGS_05,
1505 class ARGS_06,
1506 class ARGS_07,
1507 class ARGS_08,
1508 class ARGS_09>
1509 typename bsl::enable_if<
1510 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1511 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1514 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1515 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1516 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1517 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1518 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1519 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1520 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
1521 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
1522 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
1523 {
1524 bool notFound;
1525 bsl::size_t hashValue = d_hasher(key);
1526 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1527
1528 if (notFound) {
1529 ENTRY_UTIL::construct(d_entries_p + index,
1530 d_allocator_p,
1531 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1532 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1533 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1534 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
1535 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
1536 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
1537 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
1538 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
1539 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
1540
1541 d_controls_p[index] = static_cast<bsl::uint8_t>(
1542 hashValue & k_HASHLET_MASK);
1543 ++d_size;
1544 }
1545
1546 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1547 d_controls_p + index,
1548 d_capacity - index - 1),
1549 notFound);
1550 }
1551#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 9
1552
1553#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
1554 template <class LOOKUP_KEY, class ARGS_01,
1555 class ARGS_02,
1556 class ARGS_03,
1557 class ARGS_04,
1558 class ARGS_05,
1559 class ARGS_06,
1560 class ARGS_07,
1561 class ARGS_08,
1562 class ARGS_09,
1563 class ARGS_10>
1564 typename bsl::enable_if<
1565 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1566 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1569 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
1570 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
1571 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
1572 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
1573 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
1574 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
1575 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
1576 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
1577 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
1578 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
1579 {
1580 bool notFound;
1581 bsl::size_t hashValue = d_hasher(key);
1582 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1583
1584 if (notFound) {
1585 ENTRY_UTIL::construct(d_entries_p + index,
1586 d_allocator_p,
1587 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
1588 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
1589 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
1590 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
1591 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
1592 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
1593 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
1594 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
1595 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
1596 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
1597
1598 d_controls_p[index] = static_cast<bsl::uint8_t>(
1599 hashValue & k_HASHLET_MASK);
1600 ++d_size;
1601 }
1602
1603 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1604 d_controls_p + index,
1605 d_capacity - index - 1),
1606 notFound);
1607 }
1608#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_D >= 10
1609
1610#else
1611// The generated code below is a workaround for the absence of perfect
1612// forwarding in some compilers.
1613 template< class... ARGS>
1615 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS)... args);
1616
1617 template <class... ARGS>
1619 BloombergLP::bslmf::MovableRef<KEY> key,
1620 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS)... args);
1621
1622 template <class LOOKUP_KEY, class... ARGS>
1623 typename bsl::enable_if<
1624 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1625 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1629 {
1630 bool notFound;
1631 bsl::size_t hashValue = d_hasher(key);
1632 bsl::size_t index = indexOfKeyTransparent(&notFound, key, hashValue);
1633
1634 if (notFound) {
1635 ENTRY_UTIL::construct(d_entries_p + index,
1636 d_allocator_p,
1637 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
1638
1639 d_controls_p[index] = static_cast<bsl::uint8_t>(
1640 hashValue & k_HASHLET_MASK);
1641 ++d_size;
1642 }
1643
1644 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
1645 d_controls_p + index,
1646 d_capacity - index - 1),
1647 notFound);
1648 }
1649// }}} END GENERATED CODE
1650#endif
1651
1652
1653 // Iterators
1654
1655 /// Return an iterator representing the beginning of the sequence of
1656 /// entries held by this container.
1657 iterator begin();
1658
1659 /// Return an iterator representing one past the end of the sequence of
1660 /// entries held by this container.
1661 iterator end();
1662
1663 // Aspects
1664
1665 /// Efficiently exchange the value of this table with the value of the
1666 /// specified `other` table. This method provides the no-throw exception-safety guarantee.
1667 ///
1668 /// \pre The behavior is undefined unless this
1669 /// array was created with the same allocator as `other`.
1670 void swap(FlatHashTable& other);
1671
1672 // ACCESSORS
1673
1674 /// Return the number of elements this table could hold if the load
1675 /// factor were 1.
1676 bsl::size_t capacity() const;
1677
1678 /// Return `true` if this table contains an entry having the specified
1679 /// `key`, and `false` otherwise.
1680 bool contains(const KEY& key) const;
1681
1682 /// Return the address of the first element of the underlying array of
1683 /// control values in this table, or 0 if this table is in the
1684 /// zero-capacity state. An element of this array has the value
1685 /// `FlatHashTable_GroupControl::k_EMPTY`,
1686 /// `FlatHashTable_GroupControl::k_ERASED`, or a seven bit hashlet value
1687 /// for the in-use position (the highest-order bit is unset).
1688 const bsl::uint8_t *controls() const;
1689
1690 /// Return the number of objects contained within this table having the specified `key`.
1691 ///
1692 /// \note Note that since a table maintains unique keys, the
1693 /// returned value will be either 0 or 1.
1694 bsl::size_t count(const KEY& key) const;
1695
1696 /// Return `true` if this table contains no entries, and `false`
1697 /// otherwise.
1698 bool empty() const;
1699
1700 /// Return the address of the first element of the underlying array of
1701 /// entries in this table, or 0 if this table is in the zero-capacity state.
1702 ///
1703 /// \pre The behavior is undefined unless the address is verified
1704 /// in-use through use of the `controls` array before dereferencing an
1705 /// entry in this array.
1706 const ENTRY *entries() const;
1707
1708 /// Return a pair of iterators providing non-modifiable access to the
1709 /// sequence of objects in this table having the specified `key`, where
1710 /// the first iterator is positioned at the start of the sequence, and
1711 /// the second is positioned one past the end of the sequence. If this
1712 /// table contains no objects having `key`, then the two returned iterators will have the same value, `end()`.
1713 ///
1714 /// \note Note that since a
1715 /// table maintains unique keys, the range will contain at most one
1716 /// entry.
1718 const KEY& key) const;
1719
1720 /// Return a pair of iterators providing non-modifiable access to the
1721 /// sequence of objects in this table having a key equivalent to the
1722 /// specified `key`, where the first iterator is positioned at the start
1723 /// of the sequence, and the second is positioned one past the end of the
1724 /// sequence. If this table contains no objects having a key equivalent to
1725 /// the specified `key`, then the two returned iterators will have the same value, `end()`.
1726 ///
1727 /// \note Note that since a table maintains unique keys, the
1728 /// range will contain at most one entry.
1729 template <class LOOKUP_KEY>
1730 typename bsl::enable_if<
1731 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1732 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1734 equal_range(const LOOKUP_KEY& key) const
1735 {
1736 // Note: implemented inline due to Sun CC compilation error.
1737
1738 const_iterator cit1 = find(key);
1739 const_iterator cit2 = cit1;
1740 if (cit1 != end()) {
1741 ++cit2;
1742 }
1743 return bsl::make_pair(cit1, cit2);
1744 }
1745
1746 /// Return an iterator representing the position of the entry in this
1747 /// flat hash table having the specified `key`, or `end()` if no such
1748 /// entry exists in this table.
1749 const_iterator find(const KEY& key) const;
1750
1751 /// Return an iterator representing the position of the entry in this
1752 /// flat hash table that is equivalent to the specified `key`, or `end()`
1753 // if no such entry exists in this table.
1754 template <class LOOKUP_KEY>
1755 typename bsl::enable_if<
1756 BloombergLP::bslmf::IsTransparentPredicate<HASH, LOOKUP_KEY>::value
1757 && BloombergLP::bslmf::IsTransparentPredicate<EQUAL,LOOKUP_KEY>::value
1758 , const_iterator>::type
1759 find(const LOOKUP_KEY& key) const
1760 {
1761 // Note: implemented inline due to Sun CC compilation error.
1762
1763 bsl::size_t index = findTransparentKey(key, d_hasher(key));
1764 if (index < d_capacity) {
1765 return const_iterator(IteratorImp(d_entries_p + index,
1766 d_controls_p + index,
1767 d_capacity - index - 1)); // RETURN
1768 }
1769 return end();
1770 }
1771
1772 /// Return (a copy of) the unary hash functor used by this flat hash
1773 /// table to generate a hash value (of type `bsl::size_t) for a `KEY'
1774 /// object.
1775 HASH hash_function() const;
1776
1777 /// Return (a copy of) the binary key-equality functor used by this flat
1778 /// hash table that returns `true` if two `KEY` objects are equal, and
1779 /// `false` otherwise.
1780 EQUAL key_eq() const;
1781
1782 /// Return the current ratio between the number of elements in this
1783 /// table and its capacity.
1784 float load_factor() const;
1785
1786 /// Return the maximum load factor allowed for this table.
1787 /// \note Note that if
1788 /// an insert operation would cause the load factor to exceed the
1789 /// @ref max_load_factor , that same insert operation will increase the
1790 /// capacity and rehash the entries of the container (see `insert` and `rehash`).
1791 ///
1792 /// \note Note that the value returned by @ref max_load_factor is
1793 /// implementation dependent and cannot be changed by the user.
1794 float max_load_factor() const;
1795
1796 /// Return the number of entries in this table.
1797 bsl::size_t size() const;
1798
1799 // Iterators
1800
1801 const_iterator begin() const;
1802
1803 /// Return an iterator representing the beginning of the sequence of
1804 /// entries held by this container.
1805 const_iterator cbegin() const;
1806
1807 const_iterator cend() const;
1808
1809 /// Return an iterator representing one past the end of the sequence of
1810 /// entries held by this container.
1811 const_iterator end() const;
1812
1813 // Aspects
1814
1815 /// Return the allocator used by this hash table to supply memory.
1816 bslma::Allocator *allocator() const;
1817};
1818
1819// FREE OPERATORS
1820
1821/// Return `true` if the specified `lhs` and `rhs` objects have the same
1822/// value, and `false` otherwise. Two `FlatHashTable` objects have the same
1823/// value if they have the same number of entries, and for each entry that
1824/// is contained in `lhs` there is a entry contained in `rhs` having the same value.
1825///
1826/// \note Note that this method requires the (template parameter)
1827/// type `ENTRY` to be equality-comparable.
1828template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1829bool operator==(const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& lhs,
1830 const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& rhs);
1831
1832/// Return `true` if the specified `lhs` and `rhs` objects do not have the
1833/// same value, and `false` otherwise. Two `FlatHashTable` objects do not
1834/// have the same value if they do not have the same number of entries, or
1835/// that for some entry contained in `lhs` there is not a entry in `rhs` having the same value.
1836///
1837/// \note Note that this method requires the (template
1838/// parameter) type `ENTRY` to be equality-comparable.
1839template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1840bool operator!=(const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& lhs,
1841 const FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& rhs);
1842
1843// FREE FUNCTIONS
1844
1845/// Exchange the values of the specified `a` and `b` objects. This function
1846/// provides the no-throw exception-safety guarantee if the two objects were
1847/// created with the same allocator and the basic guarantee otherwise.
1848template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
1849void swap(FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& a,
1850 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& b);
1851
1852 // =============================
1853 // struct FlatHashTable_ImplUtil
1854 // =============================
1855
1856/// This component-private, utility `struct` provides a namespace for a
1857/// suite of operations used in the implementation of the `FlatHashTable`
1858/// class template.
1859///
1860/// See @ref bdlc_flathashtable_cpp03
1861struct FlatHashTable_ImplUtil {
1862
1863 private:
1864 // PRIVATE TYPES
1865 typedef FlatHashTable_GroupControl GroupControl;
1866
1867 /// This component-private, mechanism class template provides a proctor
1868 /// that, unless its `release` method has been previously invoked, on
1869 /// destruction automatically destroys the populated `ENTRY_TYPE`
1870 /// elements of an `ENTRY_TYPE` array supplied on construction as
1871 /// indicated by a "control" byte array supplied on construction.
1872 template <class ENTRY_TYPE>
1873 class DestroyEntryArrayProctor;
1874
1875 // PRIVATE CLASS METHODS
1876
1877 /// Copy the specified range `[firstSourceControl, lastSourceControl)`
1878 /// to the array specified by `firstDestinationControl`, and copy each
1879 /// element in the specified range `[firstSourceEntry, lastSourceEntry)`
1880 /// at the same index as each byte in the range '[firstSourceControl,
1881 /// lastSourceControl)' that has its most-significant bit unset, to the
1882 /// corresponding location in the contiguous storage for `ENTRY_TYPE`
1883 /// objects specified by `firstDestinationEntry`. Use the specified
1884 /// `entryAllocator` as the object allocator for each newly-constructed
1885 /// `ENTRY_TYPE` object if `ENTRY_TYPE` is allocator-aware. If
1886 /// `entryAllocator` is 0, the currently-installed default allocator is
1887 /// used. No exception is thrown if the specified `ENTRY_TYPE` is
1888 /// nothrow-copyable, otherwise an exception may be thrown.
1889 ///
1890 /// \pre The behavior is undefined unless
1891 /// `bslmf::IsBitwiseCopyable<ENTRY_TYPE>::value` is equal to the
1892 /// `value` member of the type of the specified `tag`,
1893 /// `firstDestinationEntry` is a pointer to the first byte of
1894 /// uninitialized and correctly aligned storage for at least
1895 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` `ENTRY_TYPE`
1896 /// objects, `firstDestinationControl` is a pointer to the first byte of
1897 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` bytes of
1898 /// uninitialized storage, the range '[firstSourceEntry,
1899 /// lastSourceEntry)' denotes a contiguous array of storage for
1900 /// optionally-constructed `ENTRY_TYPE` objects, the range
1901 /// `[firstSourceControl, lastSourceControl)` denotes a contiguous array
1902 /// of `bsl::uint8_t` objects, an `ENTRY_TYPE` object exists at the same
1903 /// index in the `[firstSourceEntry, lastSourceEntry)` storage range as
1904 /// each byte in the range `[firstControlEntry, lastControlEntry)` that
1905 /// has its most significant bit unset, and
1906 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` is equal to
1907 /// `bsl::distance(firstSourceControl, lastSourceControl)`.
1908 template <class ENTRY_TYPE>
1909 static void copyEntryAndControlArrays(
1910 ENTRY_TYPE *firstDestinationEntry,
1911 bsl::uint8_t *firstDestinationControl,
1912 const ENTRY_TYPE *firstSourceEntry,
1913 const ENTRY_TYPE *lastSourceEntry,
1914 const bsl::uint8_t *firstSourceControl,
1915 const bsl::uint8_t *lastSourceControl,
1916 bslma::Allocator *entryAllocator,
1917 bsl::false_type bitwiseCopyable);
1918 template <class ENTRY_TYPE>
1919 static void copyEntryAndControlArrays(
1920 ENTRY_TYPE *firstDestinationEntry,
1921 bsl::uint8_t *firstDestinationControl,
1922 const ENTRY_TYPE *firstSourceEntry,
1923 const ENTRY_TYPE *lastSourceEntry,
1924 const bsl::uint8_t *firstSourceControl,
1925 const bsl::uint8_t *lastSourceControl,
1926 bslma::Allocator *entryAllocator,
1927 bsl::true_type bitwiseCopyable);
1928
1929
1930 /// Destroy each entry object in the storage specified by the range
1931 /// `[firstEntry, lastEntry)` if the most-significant bit is unset in
1932 /// the corresponding element in the specified range
1933 /// `[firstControl, lastControl)` (i.e., the most-significant bit of the
1934 /// element in the "control" array that has the same index as the
1935 /// element in the "entry" array is unset). No exception is thrown.
1936 ///
1937 /// \pre The behavior is undefined unless
1938 /// `bslmf::IsTriviallyDestructible<ENTRY_TYPE>::value` is equal to the
1939 /// `value` member of the type of the specified `tag`, the range
1940 /// `[firstEntry, lastEntry)` denotes a contiguous array of storage for
1941 /// optionally-constructed `ENTRY_TYPE` objects, the range
1942 /// `[firstControl, lastControl)` denotes a contiguous array of
1943 /// `bsl::uint8_t` objects, the two arrays have the same number of
1944 /// elements, and an `ENTRY_TYPE` object exists at the same index in the
1945 /// `[firstEntry, lastEntry)` storage range for each element in the
1946 /// `[firstControl, lastControl)` range that has its first bit unset.
1947 template <class ENTRY_TYPE>
1948 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
1949 ENTRY_TYPE *lastEntry,
1950 const bsl::uint8_t *firstControl,
1951 const bsl::uint8_t *lastControl,
1952 bsl::false_type triviallyDestructible);
1953 template <class ENTRY_TYPE>
1954 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
1955 ENTRY_TYPE *lastEntry,
1956 const bsl::uint8_t *firstControl,
1957 const bsl::uint8_t *lastControl,
1958 bsl::true_type triviallyDestructible);
1959
1960 public:
1961 // CLASS METHODS
1962
1963 /// Copy the specified range `[firstSourceControl, lastSourceControl)`
1964 /// to the array specified by `firstDestinationControl`, and copy each
1965 /// element in the specified range `[firstSourceEntry, lastSourceEntry)`
1966 /// at the same index as each byte in the range '[firstSourceControl,
1967 /// lastSourceControl)' that has its most-significant bit unset, to the
1968 /// corresponding location in the contiguous storage for `ENTRY_TYPE`
1969 /// objects specified by `firstDestinationEntry`. Use the specified
1970 /// `entryAllocator` as the object allocator for each newly-constructed
1971 /// `ENTRY_TYPE` object if `ENTRY_TYPE` is allocator-aware. If
1972 /// `entryAllocator` is 0, the currently-installed default allocator is
1973 /// used. No exception is thrown if the specified `ENTRY_TYPE` is
1974 /// nothrow-copyable, otherwise an exception may be thrown.
1975 ///
1976 /// \pre The behavior is undefined unless `firstDestinationEntry` is a pointer to
1977 /// the first byte of uninitialized and correctly aligned storage for at
1978 /// least `bsl::distance(firstSourceEntry, lastSourceEntry)`
1979 /// `ENTRY_TYPE` objects, `firstDestinationControl` is a pointer to the
1980 /// first byte of `bsl::distance(firstSourceEntry, lastSourceEntry)`
1981 /// bytes of uninitialized storage, the range '[firstSourceEntry,
1982 /// lastSourceEntry)' denotes a contiguous array of storage for
1983 /// optionally-constructed `ENTRY_TYPE` objects, the range
1984 /// `[firstSourceControl, lastSourceControl)` denotes a contiguous array
1985 /// of `bsl::uint8_t` objects, an `ENTRY_TYPE` object exists at the same
1986 /// index in the `[firstSourceEntry, lastSourceEntry)` storage range as
1987 /// each byte in the range `[firstControlEntry, lastControlEntry)` that
1988 /// has its most significant bit unset, and
1989 /// `bsl::distance(firstSourceEntry, lastSourceEntry)` is equal to
1990 /// `bsl::distance(firstSourceControl, lastSourceControl)`.
1991 template <class ENTRY_TYPE>
1992 static void
1993 copyEntryAndControlArrays(ENTRY_TYPE *firstDestinationEntry,
1994 bsl::uint8_t *firstDestinationControl,
1995 const ENTRY_TYPE *firstSourceEntry,
1996 const ENTRY_TYPE *lastSourceEntry,
1997 const bsl::uint8_t *firstSourceControl,
1998 const bsl::uint8_t *lastSourceControl,
1999 bslma::Allocator *entryAllocator);
2000
2001 /// Destroy each entry object in the storage specified by the range
2002 /// `[firstEntry, lastEntry)` if the most-significant bit is unset in
2003 /// the corresponding element in the specified range '[firstControl,
2004 /// lastControl)' (i.e., the most-significant bit of the element in the
2005 /// "control" array that has the same index as the element in the
2006 /// "entry" array is unset). No exception is thrown.
2007 ///
2008 /// \pre The behavior is undefined unless the range `[firstEntry, lastEntry)` denotes a
2009 /// contiguous array of storage for optionally-constructed `ENTRY_TYPE`
2010 /// objects, the range `[firstControl, lastControl)` denotes a
2011 /// contiguous array of `bsl::uint8_t` objects, the two arrays have the
2012 /// same number of elements, and an `ENTRY_TYPE` object exists at the
2013 /// same index in the `[firstEntry, lastEntry)` storage range for each
2014 /// element in the `[firstControl, lastControl)` range that has its
2015 /// first bit unset.
2016 template <class ENTRY_TYPE>
2017 static void destroyEntryArray(ENTRY_TYPE *firstEntry,
2018 ENTRY_TYPE *lastEntry,
2019 const bsl::uint8_t *firstControl,
2020 const bsl::uint8_t *lastControl);
2021};
2022
2023 // ======================================================
2024 // class FlatHashTable_ImplUtil::DestroyEntryArrayProctor
2025 // ======================================================
2026
2027/// This component-private, mechanism class template provides a proctor
2028/// that, unless its `release` method has been previously invoked, on
2029/// destruction automatically destroys the populated `ENTRY_TYPE` elements
2030/// of an `ENTRY_TYPE` array supplied on construction as indicated by a
2031/// "control" byte array supplied on construction.
2032template <class ENTRY_TYPE>
2033class FlatHashTable_ImplUtil::DestroyEntryArrayProctor {
2034
2035 // PRIVATE TYPES
2036 typedef FlatHashTable_GroupControl GroupControl;
2037 typedef FlatHashTable_ImplUtil ImplUtil;
2038
2039 // DATA
2040
2041 // pointer to first element of entry array
2042 ENTRY_TYPE *d_firstEntry_p;
2043
2044 // pointer to one-past-the-end of entry array
2045 ENTRY_TYPE *d_lastEntry_p;
2046
2047 // pointer to first element of control array
2048 const bsl::uint8_t *d_firstControl_p;
2049
2050 // pointer to one-past-the-end of control array
2051 const bsl::uint8_t *d_lastControl_p;
2052
2053 private:
2054 // NOT IMPLEMENTED
2055 DestroyEntryArrayProctor(const DestroyEntryArrayProctor&);
2056 DestroyEntryArrayProctor& operator=(const DestroyEntryArrayProctor&);
2057
2058 public:
2059 // CREATORS
2060
2061 /// Create a new `DestroyEntryArrayProctor` object for the contiguous
2062 /// `ENTRY_TYPE` storage delimited by the range specified by
2063 /// `[firstEntry, lastEntry)` controlled by the bytes in the range
2064 /// specified by `[firstControl, lastControl)`.
2065 ///
2066 /// \pre The behavior is undefined unless 'bsl::distance(firstEntry, lastEntry) == bsl::distance(`firstControl, lastControl)`.
2067 ///
2068 /// \note Note that these ranges
2069 /// may be valid sub-ranges (or "views") of larger arrays, and these
2070 /// sub-ranges can be grown or shrunk by `moveEnd`.
2071 DestroyEntryArrayProctor(ENTRY_TYPE *firstEntry,
2072 ENTRY_TYPE *lastEntry,
2073 const bsl::uint8_t *firstControl,
2074 const bsl::uint8_t *lastControl);
2075
2076 /// Destroy this object and each object in the entry storage array held
2077 /// by this object where the most-significant bit of the corresponding
2078 /// element in the control array held by this object is unset.
2079 ~DestroyEntryArrayProctor();
2080
2081 // MANIPULATORS
2082
2083 /// Move the end of the entry and control ranges held by this object by
2084 /// the specified `offset`.
2085 void moveEnd(bsl::ptrdiff_t offset);
2086
2087 /// Release the entry and control ranges held by this object from
2088 /// management by this object, and set this object's held entry and
2089 /// control arrays to the corresponding empty arrays. If the entry and
2090 /// control arrays held by this object are empty, this method has no
2091 /// effect.
2092 void release();
2093};
2094
2095// ============================================================================
2096// INLINE DEFINITIONS
2097// ============================================================================
2098
2099 // -------------------------------
2100 // class FlatHashTable_IteratorImp
2101 // -------------------------------
2102
2103// CREATORS
2104template <class ENTRY>
2105inline
2107: d_entries_p(0)
2108, d_controls_p(0)
2109, d_additionalLength(0)
2110{
2111}
2112
2113template <class ENTRY>
2114inline
2115FlatHashTable_IteratorImp<ENTRY>::FlatHashTable_IteratorImp(
2116 ENTRY *entries,
2117 const bsl::uint8_t *controls,
2118 bsl::size_t additionalLength)
2119: d_entries_p(entries)
2120, d_controls_p(controls)
2121, d_additionalLength(additionalLength)
2122{
2123}
2124
2125template <class ENTRY>
2126inline
2127FlatHashTable_IteratorImp<ENTRY>::FlatHashTable_IteratorImp(
2128 const FlatHashTable_IteratorImp& original)
2129: d_entries_p(original.d_entries_p)
2130, d_controls_p(original.d_controls_p)
2131, d_additionalLength(original.d_additionalLength)
2132{
2133}
2134
2135// MANIPULATORS
2136template <class ENTRY>
2137inline
2138FlatHashTable_IteratorImp<ENTRY>& FlatHashTable_IteratorImp<ENTRY>::operator=(
2139 const FlatHashTable_IteratorImp& rhs)
2140{
2141 d_entries_p = rhs.d_entries_p;
2142 d_controls_p = rhs.d_controls_p;
2143 d_additionalLength = rhs.d_additionalLength;
2144
2145 return *this;
2146}
2147
2148template <class ENTRY>
2149inline
2150void FlatHashTable_IteratorImp<ENTRY>::operator++()
2151{
2152 BSLS_ASSERT_SAFE(d_entries_p);
2153 BSLS_ASSERT_SAFE(d_controls_p);
2154
2155 while (d_additionalLength) {
2156 ++d_entries_p;
2157 ++d_controls_p;
2158 --d_additionalLength;
2159 if (0 == (*d_controls_p & 0x80)) {
2160 return; // RETURN
2161 }
2162 }
2163
2164 d_entries_p = 0;
2165 d_controls_p = 0;
2166}
2167
2168// ACCESSORS
2169template <class ENTRY>
2170inline
2171ENTRY& FlatHashTable_IteratorImp<ENTRY>::operator*() const
2172{
2173 BSLS_ASSERT_SAFE(d_entries_p);
2174 BSLS_ASSERT_SAFE(d_controls_p);
2175
2176 return *d_entries_p;
2177}
2178
2179} // close package namespace
2180
2181// FREE OPERATORS
2182template <class ENTRY>
2183inline
2184bool bdlc::operator==(const FlatHashTable_IteratorImp<ENTRY>& a,
2185 const FlatHashTable_IteratorImp<ENTRY>& b)
2186{
2187 return a.d_entries_p == b.d_entries_p
2188 && a.d_controls_p == b.d_controls_p
2189 && a.d_additionalLength == b.d_additionalLength;
2190}
2191
2192namespace bdlc {
2193
2194 // -------------------
2195 // class FlatHashTable
2196 // -------------------
2197
2198// PRIVATE CLASS METHODS
2199template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2200bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::findAvailable(
2201 bsl::uint8_t *controls,
2202 bsl::size_t index,
2203 bsl::size_t capacity)
2204{
2205 BSLS_ASSERT_SAFE(index < capacity);
2206
2207 for (bsl::size_t i = 0; i < capacity; i += GroupControl::k_SIZE) {
2208 bsl::uint8_t *controlStart = controls + index;
2209
2210 GroupControl groupControl(controlStart);
2211 bsl::uint32_t candidates = groupControl.available();
2212
2213 if (candidates) {
2214 return index
2215 + bdlb::BitUtil::numTrailingUnsetBits(candidates); // RETURN
2216 }
2217
2218 index = (index + GroupControl::k_SIZE) & (capacity - 1);
2219 }
2220
2221 BSLS_ASSERT_OPT_UNREACHABLE("FlatHash ran out of available slots,"
2222 " even though it should have found one");
2223 return capacity;
2224}
2225
2226// PRIVATE MANIPULATORS
2227template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2228bsl::size_t FlatHashTable<KEY,
2229 ENTRY,
2230 ENTRY_UTIL,
2231 HASH,
2232 EQUAL>::indexOfKey(bool *notFound,
2233 const KEY& key,
2234 bsl::size_t hashValue)
2235{
2236 BSLS_ASSERT_SAFE(hashValue == d_hasher(key));
2237
2238 bsl::size_t index = findKey(key, hashValue);
2239
2240 if (index == d_capacity) {
2241 *notFound = true;
2242
2243 if (d_size >= k_MAX_LOAD_FACTOR_NUMERATOR
2244 * (d_capacity / k_MAX_LOAD_FACTOR_DENOMINATOR)) {
2245 rehashRaw(d_capacity > 0 ? 2 * d_capacity : k_MIN_CAPACITY);
2246 }
2247
2248 index = (hashValue >> d_groupControlShift) * GroupControl::k_SIZE;
2249 index = findAvailable(d_controls_p, index, d_capacity);
2250 }
2251 else {
2252 *notFound = false;
2253 }
2254
2255 return index;
2256}
2257
2258template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2259void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::rehashRaw(
2260 bsl::size_t newCapacity)
2261{
2262 BSLS_ASSERT_SAFE( 0 < newCapacity);
2263 BSLS_ASSERT_SAFE(newCapacity == minimumCompliantCapacity(newCapacity));
2264
2265 FlatHashTable tmp(newCapacity,
2266 d_hasher,
2267 d_equal,
2268 d_allocator_p);
2269
2270 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
2271 bsl::uint8_t *controlStart = d_controls_p + i;
2272 ENTRY *entryStart = d_entries_p + i;
2273
2274 GroupControl groupControl(controlStart);
2275 bsl::uint32_t candidates = groupControl.inUse();
2276 while (candidates) {
2277 int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
2278 ENTRY *entry = entryStart + offset;
2279
2280 // create a destructor proctor for the element to be moved
2281 bslma::DestructorProctor<ENTRY> proctor(entry);
2282
2283 // perform book-keeping for the destruction
2284 *(controlStart + offset) = GroupControl::k_ERASED;
2285 --d_size;
2286
2287 // place the element in the new container
2288 bsl::size_t hashValue = tmp.d_hasher(ENTRY_UTIL::key(*entry));
2289 bsl::size_t index = (hashValue >> tmp.d_groupControlShift)
2290 * GroupControl::k_SIZE;
2291
2292 index = findAvailable(tmp.d_controls_p, index, tmp.d_capacity);
2293
2294 bslma::ConstructionUtil::destructiveMove(tmp.d_entries_p + index,
2295 tmp.d_allocator_p,
2296 entry);
2297
2298 // release destructor proctor
2299 proctor.release();
2300
2301 tmp.d_controls_p[index] = static_cast<bsl::uint8_t>(
2302 hashValue & k_HASHLET_MASK);
2303
2304 ++tmp.d_size;
2305
2306 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
2307 }
2308 }
2309
2310 d_allocator_p->deallocate(d_entries_p);
2311 d_allocator_p->deallocate(d_controls_p);
2312
2313 d_entries_p = 0;
2314 d_controls_p = 0;
2315 d_capacity = 0;
2316 d_groupControlShift = 0;
2317
2318 bslalg::SwapUtil::swap(&d_entries_p, &tmp.d_entries_p);
2319 bslalg::SwapUtil::swap(&d_controls_p, &tmp.d_controls_p);
2320 bslalg::SwapUtil::swap(&d_size, &tmp.d_size);
2321 bslalg::SwapUtil::swap(&d_capacity, &tmp.d_capacity);
2322 bslalg::SwapUtil::swap(&d_groupControlShift, &tmp.d_groupControlShift);
2323}
2324
2325// PRIVATE ACCESSORS
2326template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2327bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::findKey(
2328 const KEY& key,
2329 bsl::size_t hashValue) const
2330{
2331 BSLS_ASSERT_SAFE(hashValue == d_hasher(key));
2332
2333 bsl::size_t index = (hashValue >> d_groupControlShift)
2334 * GroupControl::k_SIZE;
2335 bsl::uint8_t hashlet = static_cast<bsl::uint8_t>(
2336 hashValue & k_HASHLET_MASK);
2337
2338 for (bsl::size_t i = 0; i < d_capacity; i += GroupControl::k_SIZE) {
2339 bsl::uint8_t *controlStart = d_controls_p + index;
2340 ENTRY *entryStart = d_entries_p + index;
2341
2342 GroupControl groupControl(controlStart);
2343 bsl::uint32_t candidates = groupControl.match(hashlet);
2344 while (candidates) {
2345 int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
2346
2347 ENTRY *entry = entryStart + offset;
2348
2350 d_equal(ENTRY_UTIL::key(*entry), key))) {
2351 return index + offset; // RETURN
2352 }
2353 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
2354 }
2355 if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(groupControl.neverFull())) {
2356 break;
2357 }
2358
2359 index = (index + GroupControl::k_SIZE) & (d_capacity - 1);
2360 }
2361
2362 return d_capacity;
2363}
2364
2365template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2366bsl::size_t FlatHashTable<KEY,
2367 ENTRY,
2368 ENTRY_UTIL,
2369 HASH,
2370 EQUAL>::minimumCompliantCapacity(
2371 bsl::size_t minimumCapacity) const
2372{
2373 bsl::size_t minForEntries = ((d_size + k_MAX_LOAD_FACTOR_NUMERATOR - 1)
2374 / k_MAX_LOAD_FACTOR_NUMERATOR)
2375 * k_MAX_LOAD_FACTOR_DENOMINATOR;
2376
2377 bsl::size_t capacity = minimumCapacity >= minForEntries
2378 ? minimumCapacity
2379 : minForEntries;
2380
2381 if (0 < capacity) {
2382 capacity = capacity > k_MIN_CAPACITY
2383 ? static_cast<bsl::size_t>(bdlb::BitUtil::roundUpToBinaryPower(
2384 static_cast<bsl::uint64_t>(capacity)))
2385 : k_MIN_CAPACITY;
2386 }
2387
2388 return capacity;
2389}
2390
2391// CREATORS
2392template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2393inline
2394FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
2395 bsl::size_t capacity,
2396 const HASH& hash,
2397 const EQUAL& equal,
2398 bslma::Allocator *basicAllocator)
2399: d_entries_p(0)
2400, d_controls_p(0)
2401, d_size(0)
2402, d_capacity(0)
2403, d_groupControlShift(0)
2404, d_hasher(hash)
2405, d_equal(equal)
2406, d_allocator_p(bslma::Default::allocator(basicAllocator))
2407{
2408 if (0 < capacity) {
2409 d_capacity = capacity > k_MIN_CAPACITY
2410 ? static_cast<bsl::size_t>(bdlb::BitUtil::roundUpToBinaryPower(
2411 static_cast<bsl::uint64_t>(capacity)))
2412 : k_MIN_CAPACITY;
2413
2414 d_groupControlShift = static_cast<int>(
2415 sizeof(bsl::size_t) * 8
2416 - bdlb::BitUtil::log2(static_cast<bsl::uint64_t>(
2417 d_capacity
2418 / GroupControl::k_SIZE)));
2419
2420 ENTRY *entries = static_cast<ENTRY *>(
2421 d_allocator_p->allocate(d_capacity * sizeof(ENTRY)));
2422
2424 d_allocator_p);
2425
2426 d_controls_p = static_cast<bsl::uint8_t *>(
2427 d_allocator_p->allocate(d_capacity));
2428 bsl::memset(d_controls_p, GroupControl::k_EMPTY, d_capacity);
2429
2430 proctor.release();
2431 d_entries_p = entries;
2432 }
2433}
2434
2435template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2436inline
2437FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
2438 const FlatHashTable& original,
2439 bslma::Allocator *basicAllocator)
2440: d_entries_p(0)
2441, d_controls_p(0)
2442, d_size(0)
2443, d_capacity(0)
2444, d_groupControlShift(0)
2445, d_hasher(original.hash_function())
2446, d_equal(original.key_eq())
2447, d_allocator_p(bslma::Default::allocator(basicAllocator))
2448{
2449 if (0 != original.d_capacity) {
2450 bsl::uint8_t *const controls = static_cast<bsl::uint8_t *>(
2451 d_allocator_p->allocate(original.d_capacity));
2453 controls,
2454 d_allocator_p);
2455
2456 ENTRY *const entries = static_cast<ENTRY *>(
2457 d_allocator_p->allocate(original.d_capacity * sizeof(ENTRY)));
2459 entries,
2460 d_allocator_p);
2461
2462 ImplUtil::copyEntryAndControlArrays(
2463 entries,
2464 controls,
2465 original.d_entries_p,
2466 original.d_entries_p + original.d_capacity,
2467 original.d_controls_p,
2468 original.d_controls_p + original.d_capacity,
2469 d_allocator_p);
2470
2471 entriesProctor.release();
2472 controlsProctor.release();
2473
2474 d_entries_p = entries;
2475 d_controls_p = controls;
2476 d_size = original.d_size;
2477 d_capacity = original.d_capacity;
2478 d_groupControlShift = original.d_groupControlShift;
2479 }
2480}
2481
2482template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2483inline
2484FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
2486: d_entries_p(bslmf::MovableRefUtil::access(original).d_entries_p)
2487, d_controls_p(bslmf::MovableRefUtil::access(original).d_controls_p)
2488, d_size(bslmf::MovableRefUtil::access(original).d_size)
2489, d_capacity(bslmf::MovableRefUtil::access(original).d_capacity)
2490, d_groupControlShift(
2491 bslmf::MovableRefUtil::access(original).d_groupControlShift)
2492, d_hasher(bslmf::MovableRefUtil::access(original).d_hasher)
2493, d_equal(bslmf::MovableRefUtil::access(original).d_equal)
2494, d_allocator_p(bslmf::MovableRefUtil::access(original).d_allocator_p)
2495{
2496 FlatHashTable& reference = original;
2497
2498 reference.d_entries_p = 0;
2499 reference.d_controls_p = 0;
2500 reference.d_size = 0;
2501 reference.d_capacity = 0;
2502 reference.d_groupControlShift = 0;
2503}
2504
2505template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2506FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::FlatHashTable(
2508 bslma::Allocator *basicAllocator)
2509: d_entries_p(0)
2510, d_controls_p(0)
2511, d_size(0)
2512, d_capacity(0)
2513, d_groupControlShift(0)
2514, d_hasher(bslmf::MovableRefUtil::access(original).d_hasher)
2515, d_equal(bslmf::MovableRefUtil::access(original).d_equal)
2516, d_allocator_p(bslma::Default::allocator(basicAllocator))
2517{
2518 FlatHashTable& reference = original;
2519 if (d_allocator_p == reference.d_allocator_p) {
2520 bslalg::SwapUtil::swap(&d_entries_p, &reference.d_entries_p);
2521 bslalg::SwapUtil::swap(&d_controls_p, &reference.d_controls_p);
2522 bslalg::SwapUtil::swap(&d_size, &reference.d_size);
2523 bslalg::SwapUtil::swap(&d_capacity, &reference.d_capacity);
2524 bslalg::SwapUtil::swap(&d_groupControlShift,
2525 &reference.d_groupControlShift);
2526 }
2527 else if (reference.d_capacity) {
2528 bsl::uint8_t *const controls = static_cast<bsl::uint8_t *>(
2529 d_allocator_p->allocate(reference.d_capacity));
2531 controls,
2532 d_allocator_p);
2533
2534 ENTRY *const entries = static_cast<ENTRY *>(
2535 d_allocator_p->allocate(reference.d_capacity * sizeof(ENTRY)));
2537 entries,
2538 d_allocator_p);
2539
2540 ImplUtil::copyEntryAndControlArrays(
2541 entries,
2542 controls,
2543 reference.d_entries_p,
2544 reference.d_entries_p + reference.d_capacity,
2545 reference.d_controls_p,
2546 reference.d_controls_p + reference.d_capacity,
2547 d_allocator_p);
2548
2549 entriesProctor.release();
2550 controlsProctor.release();
2551
2552 d_entries_p = entries;
2553 d_controls_p = controls;
2554 d_size = reference.d_size;
2555 d_capacity = reference.d_capacity;
2556 d_groupControlShift = reference.d_groupControlShift;
2557 }
2558}
2559
2560template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2561inline
2562FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::~FlatHashTable()
2563{
2565 (d_capacity == 0 && d_groupControlShift == 0) ||
2566 (d_groupControlShift ==
2567 static_cast<int>(sizeof(bsl::size_t) * 8 -
2568 bdlb::BitUtil::log2(static_cast<bsl::uint64_t>(
2569 d_capacity / GroupControl::k_SIZE)))));
2570
2571 if (0 != d_entries_p) {
2572 ImplUtil::destroyEntryArray(d_entries_p,
2573 d_entries_p + d_capacity,
2574 d_controls_p,
2575 d_controls_p + d_capacity);
2576
2577 d_allocator_p->deallocate(d_entries_p);
2578 d_allocator_p->deallocate(d_controls_p);
2579 }
2580}
2581
2582// MANIPULATORS
2583template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2584inline
2585FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>&
2586FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::operator=(
2587 const FlatHashTable& rhs)
2588{
2589 if (this != &rhs) {
2590 FlatHashTable tmp(rhs, d_allocator_p);
2591 swap(tmp);
2592 }
2593 return *this;
2594}
2595
2596template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2597inline
2598FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>&
2599FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::operator=(
2601{
2602 FlatHashTable& reference = rhs;
2603 if (this != &reference) {
2604 FlatHashTable table(bslmf::MovableRefUtil::move(reference),
2605 d_allocator_p);
2606 swap(table);
2607 }
2608 return *this;
2609}
2610
2611template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2612template <class KEY_TYPE>
2613inline
2614ENTRY& FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::operator[](
2616{
2617 bool notFound;
2618 bsl::size_t hashValue = d_hasher(key);
2619 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
2620
2621 if (notFound) {
2622 ENTRY_UTIL::constructFromKey(d_entries_p + index,
2623 d_allocator_p,
2624 BSLS_COMPILERFEATURES_FORWARD(KEY_TYPE, key));
2625
2626 d_controls_p[index] = static_cast<bsl::uint8_t>(
2627 hashValue & k_HASHLET_MASK);
2628
2629 ++d_size;
2630 }
2631
2632 return d_entries_p[index];
2633}
2634
2635template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2636inline
2637void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::clear()
2638{
2639 ImplUtil::destroyEntryArray(d_entries_p,
2640 d_entries_p + d_capacity,
2641 d_controls_p,
2642 d_controls_p + d_capacity);
2643
2644 if (d_controls_p) {
2645 bsl::memset(d_controls_p, GroupControl::k_EMPTY, d_capacity);
2646 }
2647
2648 d_size = 0;
2649}
2650
2651template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2652inline
2653bsl::pair<
2654 typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2655 typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator>
2656FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::equal_range(const KEY& key)
2657{
2658 iterator it1 = find(key);
2659 if (it1 == end()) {
2660 return bsl::make_pair(it1, it1); // RETURN
2661 }
2662 iterator it2 = it1;
2663 ++it2;
2664 return bsl::make_pair(it1, it2);
2665}
2666
2667#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
2668// {{{ BEGIN GENERATED CODE
2669// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
2670#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
2671#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
2672#endif
2673#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E
2674#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E BDLC_FLATHASHTABLE_VARIADIC_LIMIT
2675#endif
2676#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 0
2677template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2678inline
2679bsl::pair<typename
2680 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2681 bool>
2682FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2683 )
2684{
2686 ENTRY_UTIL::construct(value.address(),
2687 d_allocator_p);
2688
2690 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2691}
2692#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 0
2693
2694#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 1
2695template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2696template< class ARGS_01>
2697inline
2698bsl::pair<typename
2699 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2700 bool>
2701FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2702 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
2703{
2705 ENTRY_UTIL::construct(value.address(),
2706 d_allocator_p,
2707 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
2708
2710 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2711}
2712#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 1
2713
2714#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 2
2715template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2716template< class ARGS_01,
2717 class ARGS_02>
2718inline
2719bsl::pair<typename
2720 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2721 bool>
2722FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2723 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2724 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
2725{
2727 ENTRY_UTIL::construct(value.address(),
2728 d_allocator_p,
2729 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2730 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
2731
2733 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2734}
2735#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 2
2736
2737#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 3
2738template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2739template< class ARGS_01,
2740 class ARGS_02,
2741 class ARGS_03>
2742inline
2743bsl::pair<typename
2744 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2745 bool>
2746FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2747 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2748 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2749 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
2750{
2752 ENTRY_UTIL::construct(value.address(),
2753 d_allocator_p,
2754 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2755 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2756 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
2757
2759 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2760}
2761#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 3
2762
2763#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 4
2764template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2765template< class ARGS_01,
2766 class ARGS_02,
2767 class ARGS_03,
2768 class ARGS_04>
2769inline
2770bsl::pair<typename
2771 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2772 bool>
2773FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2774 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2775 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2776 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2777 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
2778{
2780 ENTRY_UTIL::construct(value.address(),
2781 d_allocator_p,
2782 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2783 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2784 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2785 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
2786
2788 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2789}
2790#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 4
2791
2792#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 5
2793template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2794template< class ARGS_01,
2795 class ARGS_02,
2796 class ARGS_03,
2797 class ARGS_04,
2798 class ARGS_05>
2799inline
2800bsl::pair<typename
2801 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2802 bool>
2803FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2804 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2805 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2806 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2807 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2808 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
2809{
2811 ENTRY_UTIL::construct(value.address(),
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
2820 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2821}
2822#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 5
2823
2824#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 6
2825template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2826template< class ARGS_01,
2827 class ARGS_02,
2828 class ARGS_03,
2829 class ARGS_04,
2830 class ARGS_05,
2831 class ARGS_06>
2832inline
2833bsl::pair<typename
2834 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2835 bool>
2836FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2837 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2838 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2839 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2840 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2841 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2842 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
2843{
2845 ENTRY_UTIL::construct(value.address(),
2846 d_allocator_p,
2847 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2848 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2849 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2850 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2851 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2852 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
2853
2855 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2856}
2857#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 6
2858
2859#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 7
2860template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2861template< class ARGS_01,
2862 class ARGS_02,
2863 class ARGS_03,
2864 class ARGS_04,
2865 class ARGS_05,
2866 class ARGS_06,
2867 class ARGS_07>
2868inline
2869bsl::pair<typename
2870 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2871 bool>
2872FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2873 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2874 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2875 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2876 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2877 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2878 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2879 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
2880{
2882 ENTRY_UTIL::construct(value.address(),
2883 d_allocator_p,
2884 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2885 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2886 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2887 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2888 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2889 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2890 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
2891
2893 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2894}
2895#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 7
2896
2897#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 8
2898template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2899template< class ARGS_01,
2900 class ARGS_02,
2901 class ARGS_03,
2902 class ARGS_04,
2903 class ARGS_05,
2904 class ARGS_06,
2905 class ARGS_07,
2906 class ARGS_08>
2907inline
2908bsl::pair<typename
2909 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2910 bool>
2911FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2912 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2913 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2914 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2915 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2916 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2917 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2918 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2919 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
2920{
2922 ENTRY_UTIL::construct(value.address(),
2923 d_allocator_p,
2924 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2925 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2926 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2927 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2928 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2929 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2930 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2931 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
2932
2934 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2935}
2936#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 8
2937
2938#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 9
2939template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2940template< class ARGS_01,
2941 class ARGS_02,
2942 class ARGS_03,
2943 class ARGS_04,
2944 class ARGS_05,
2945 class ARGS_06,
2946 class ARGS_07,
2947 class ARGS_08,
2948 class ARGS_09>
2949inline
2950bsl::pair<typename
2951 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2952 bool>
2953FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2954 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
2955 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
2956 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
2957 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
2958 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
2959 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
2960 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
2961 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
2962 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
2963{
2965 ENTRY_UTIL::construct(value.address(),
2966 d_allocator_p,
2967 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
2968 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
2969 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
2970 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
2971 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
2972 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
2973 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
2974 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
2975 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
2976
2978 return this->insert(bslmf::MovableRefUtil::move(value.object()));
2979}
2980#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 9
2981
2982#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 10
2983template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
2984template< class ARGS_01,
2985 class ARGS_02,
2986 class ARGS_03,
2987 class ARGS_04,
2988 class ARGS_05,
2989 class ARGS_06,
2990 class ARGS_07,
2991 class ARGS_08,
2992 class ARGS_09,
2993 class ARGS_10>
2994inline
2995bsl::pair<typename
2996 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
2997 bool>
2998FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
2999 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3000 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3001 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3002 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3003 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3004 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3005 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3006 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
3007 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
3008 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
3009{
3011 ENTRY_UTIL::construct(value.address(),
3012 d_allocator_p,
3013 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3014 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3015 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3016 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3017 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3018 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3019 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3020 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
3021 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
3022 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
3023
3025 return this->insert(bslmf::MovableRefUtil::move(value.object()));
3026}
3027#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_E >= 10
3028
3029#else
3030// The generated code below is a workaround for the absence of perfect
3031// forwarding in some compilers.
3032template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3033template< class... ARGS>
3034inline
3035bsl::pair<typename
3036 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3037 bool>
3038FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::emplace(
3040{
3042 ENTRY_UTIL::construct(value.address(),
3043 d_allocator_p,
3044 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
3045
3047 return this->insert(bslmf::MovableRefUtil::move(value.object()));
3048}
3049// }}} END GENERATED CODE
3050#endif
3051
3052
3053template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3054inline
3055bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
3056 const KEY& key)
3057{
3058 iterator it = find(key);
3059 if (it == end()) {
3060 return 0; // RETURN
3061 }
3062 erase(it);
3063 return 1;
3064}
3065
3066template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3067inline
3068typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
3069FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
3070 typename FlatHashTable<KEY,
3071 ENTRY,
3072 ENTRY_UTIL,
3073 HASH,
3074 EQUAL>::const_iterator position)
3075{
3076 BSLS_ASSERT_SAFE(position != end());
3077
3078 bsl::size_t index = &*position - d_entries_p;
3079 bslma::DestructionUtil::destroy(d_entries_p + index);
3080 d_controls_p[index] = GroupControl::k_ERASED;
3081 --d_size;
3082
3083 if (d_size) {
3084 for (bsl::size_t i = index + 1; i < d_capacity; ++i) {
3085 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
3086 return iterator(IteratorImp(d_entries_p + i,
3087 d_controls_p + i,
3088 d_capacity - i - 1)); // RETURN
3089 }
3090 }
3091 }
3092 return iterator();
3093}
3094
3095template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3096inline
3097typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
3098FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
3099 typename FlatHashTable<KEY,
3100 ENTRY,
3101 ENTRY_UTIL,
3102 HASH,
3103 EQUAL>::iterator position)
3104{
3105 // Note that this overload is necessary to avoid ambiguity when the key is
3106 // a table iterator.
3107
3108 BSLS_ASSERT_SAFE(position != end());
3109
3110 bsl::size_t index = &*position - d_entries_p;
3111 bslma::DestructionUtil::destroy(d_entries_p + index);
3112 d_controls_p[index] = GroupControl::k_ERASED;
3113 --d_size;
3114
3115 if (d_size) {
3116 for (bsl::size_t i = index + 1; i < d_capacity; ++i) {
3117 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
3118 return iterator(IteratorImp(d_entries_p + i,
3119 d_controls_p + i,
3120 d_capacity - i - 1)); // RETURN
3121 }
3122 }
3123 }
3124 return iterator();
3125}
3126
3127template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3128typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
3129FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::erase(
3130 typename FlatHashTable<KEY,
3131 ENTRY,
3132 ENTRY_UTIL,
3133 HASH,
3134 EQUAL>::const_iterator first,
3135 typename FlatHashTable<KEY,
3136 ENTRY,
3137 ENTRY_UTIL,
3138 HASH,
3139 EQUAL>::const_iterator last)
3140{
3141 iterator rv;
3142 {
3143 if (last != end()) {
3144 bsl::size_t index = &*last - d_entries_p;
3145 rv = iterator(IteratorImp(d_entries_p + index,
3146 d_controls_p + index,
3147 d_capacity - index - 1));
3148 }
3149 else {
3150 rv = end();
3151 }
3152 }
3153
3154 for (; first != last; ++first) {
3155 erase(first);
3156 }
3157
3158 return rv;
3159}
3160
3161template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3162inline
3163typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
3164FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::find(const KEY& key)
3165{
3166 bsl::size_t index = findKey(key, d_hasher(key));
3167 if (index < d_capacity) {
3168 return iterator(IteratorImp(d_entries_p + index,
3169 d_controls_p + index,
3170 d_capacity - index - 1)); // RETURN
3171 }
3172 return end();
3173}
3174
3175template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3176inline
3178FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::insert(const ENTRY& entry)
3179{
3180 bool notFound;
3181 bsl::size_t hashValue = d_hasher(ENTRY_UTIL::key(entry));
3182 bsl::size_t index = indexOfKey(&notFound,
3183 ENTRY_UTIL::key(entry),
3184 hashValue);
3185
3186 if (notFound) {
3187 ENTRY_UTIL::construct(d_entries_p + index, d_allocator_p, entry);
3188 d_controls_p[index] = static_cast<bsl::uint8_t>(
3189 hashValue & k_HASHLET_MASK);
3190 ++d_size;
3191 }
3192
3193 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3194 d_controls_p + index,
3195 d_capacity - index - 1),
3196 notFound);
3197}
3198
3199template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3200inline
3202FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::insert(
3204{
3205 bool notFound;
3206 bsl::size_t hashValue = d_hasher(ENTRY_UTIL::key(entry));
3207 bsl::size_t index = indexOfKey(&notFound,
3208 ENTRY_UTIL::key(entry),
3209 hashValue);
3210
3211 if (notFound) {
3212 ENTRY_UTIL::construct(d_entries_p + index,
3213 d_allocator_p,
3214 BSLS_COMPILERFEATURES_FORWARD(ENTRY, entry));
3215
3216 d_controls_p[index] = static_cast<bsl::uint8_t>(
3217 hashValue & k_HASHLET_MASK);
3218
3219 ++d_size;
3220 }
3221
3222 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3223 d_controls_p + index,
3224 d_capacity - index - 1),
3225 notFound);
3226}
3227
3228template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3229template <class INPUT_ITERATOR>
3230inline
3231void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::insert(
3232 INPUT_ITERATOR first,
3233 INPUT_ITERATOR last)
3234{
3235 for (; first != last; ++first) {
3236 insert(*first);
3237 }
3238}
3239
3240template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3241inline
3242void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::rehash(
3243 bsl::size_t minimumCapacity)
3244{
3245 minimumCapacity = minimumCompliantCapacity(minimumCapacity);
3246
3247 if (0 < minimumCapacity) {
3248 rehashRaw(minimumCapacity);
3249 }
3250 else {
3251 d_allocator_p->deallocate(d_entries_p);
3252 d_allocator_p->deallocate(d_controls_p);
3253
3254 d_entries_p = 0;
3255 d_controls_p = 0;
3256 d_capacity = 0;
3257 d_groupControlShift = 0;
3258 }
3259}
3260
3261template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3262inline
3263void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::reserve(
3264 bsl::size_t numEntries)
3265{
3266 if (0 == d_capacity && 0 == numEntries) {
3267 // From DRQS 167247593, 'reserve(0)' on an empty container is a
3268 // performance concern.
3269
3270 return; // RETURN
3271 }
3272
3273 bsl::size_t minForEntries = ((numEntries + k_MAX_LOAD_FACTOR_NUMERATOR - 1)
3274 / k_MAX_LOAD_FACTOR_NUMERATOR)
3275 * k_MAX_LOAD_FACTOR_DENOMINATOR;
3276
3277 rehash(minForEntries);
3278}
3279
3280template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3281inline
3282void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::reset()
3283{
3284 if (0 != d_entries_p) {
3285 ImplUtil::destroyEntryArray(d_entries_p,
3286 d_entries_p + d_capacity,
3287 d_controls_p,
3288 d_controls_p + d_capacity);
3289
3290 d_allocator_p->deallocate(d_entries_p);
3291 d_allocator_p->deallocate(d_controls_p);
3292
3293 d_entries_p = 0;
3294 d_controls_p = 0;
3295 d_capacity = 0;
3296 d_size = 0;
3297 d_groupControlShift = 0;
3298 }
3299}
3300
3301#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES
3302// {{{ BEGIN GENERATED CODE
3303// Command line: sim_cpp11_features.pl bdlc_flathashtable.h
3304#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT
3305#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT 10
3306#endif
3307#ifndef BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F
3308#define BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F BDLC_FLATHASHTABLE_VARIADIC_LIMIT
3309#endif
3310#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 0
3311template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3312bsl::pair<typename
3313 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3314 bool>
3315FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3316 const KEY& key)
3317{
3318 bool notFound;
3319 bsl::size_t hashValue = d_hasher(key);
3320 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3321
3322 if (notFound) {
3323 ENTRY_UTIL::construct(d_entries_p + index,
3324 d_allocator_p);
3325
3326 d_controls_p[index] = static_cast<bsl::uint8_t>(
3327 hashValue & k_HASHLET_MASK);
3328 ++d_size;
3329 }
3330
3331 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3332 d_controls_p + index,
3333 d_capacity - index - 1),
3334 notFound);
3335}
3336#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 0
3337
3338#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 1
3339template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3340template< class ARGS_01>
3341bsl::pair<typename
3342 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3343 bool>
3344FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3345 const KEY& key,
3346 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
3347{
3348 bool notFound;
3349 bsl::size_t hashValue = d_hasher(key);
3350 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3351
3352 if (notFound) {
3353 ENTRY_UTIL::construct(d_entries_p + index,
3354 d_allocator_p,
3355 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
3356
3357 d_controls_p[index] = static_cast<bsl::uint8_t>(
3358 hashValue & k_HASHLET_MASK);
3359 ++d_size;
3360 }
3361
3362 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3363 d_controls_p + index,
3364 d_capacity - index - 1),
3365 notFound);
3366}
3367#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 1
3368
3369#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 2
3370template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3371template< class ARGS_01,
3372 class ARGS_02>
3373bsl::pair<typename
3374 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3375 bool>
3376FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3377 const KEY& key,
3378 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3379 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
3380{
3381 bool notFound;
3382 bsl::size_t hashValue = d_hasher(key);
3383 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3384
3385 if (notFound) {
3386 ENTRY_UTIL::construct(d_entries_p + index,
3387 d_allocator_p,
3388 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3389 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
3390
3391 d_controls_p[index] = static_cast<bsl::uint8_t>(
3392 hashValue & k_HASHLET_MASK);
3393 ++d_size;
3394 }
3395
3396 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3397 d_controls_p + index,
3398 d_capacity - index - 1),
3399 notFound);
3400}
3401#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 2
3402
3403#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 3
3404template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3405template< class ARGS_01,
3406 class ARGS_02,
3407 class ARGS_03>
3408bsl::pair<typename
3409 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3410 bool>
3411FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3412 const KEY& key,
3413 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3414 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3415 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
3416{
3417 bool notFound;
3418 bsl::size_t hashValue = d_hasher(key);
3419 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3420
3421 if (notFound) {
3422 ENTRY_UTIL::construct(d_entries_p + index,
3423 d_allocator_p,
3424 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3425 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3426 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
3427
3428 d_controls_p[index] = static_cast<bsl::uint8_t>(
3429 hashValue & k_HASHLET_MASK);
3430 ++d_size;
3431 }
3432
3433 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3434 d_controls_p + index,
3435 d_capacity - index - 1),
3436 notFound);
3437}
3438#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 3
3439
3440#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 4
3441template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3442template< class ARGS_01,
3443 class ARGS_02,
3444 class ARGS_03,
3445 class ARGS_04>
3446bsl::pair<typename
3447 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3448 bool>
3449FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3450 const KEY& key,
3451 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3452 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3453 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3454 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
3455{
3456 bool notFound;
3457 bsl::size_t hashValue = d_hasher(key);
3458 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3459
3460 if (notFound) {
3461 ENTRY_UTIL::construct(d_entries_p + index,
3462 d_allocator_p,
3463 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3464 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3465 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3466 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
3467
3468 d_controls_p[index] = static_cast<bsl::uint8_t>(
3469 hashValue & k_HASHLET_MASK);
3470 ++d_size;
3471 }
3472
3473 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3474 d_controls_p + index,
3475 d_capacity - index - 1),
3476 notFound);
3477}
3478#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 4
3479
3480#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 5
3481template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3482template< class ARGS_01,
3483 class ARGS_02,
3484 class ARGS_03,
3485 class ARGS_04,
3486 class ARGS_05>
3487bsl::pair<typename
3488 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3489 bool>
3490FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3491 const KEY& key,
3492 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3493 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3494 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3495 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3496 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
3497{
3498 bool notFound;
3499 bsl::size_t hashValue = d_hasher(key);
3500 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3501
3502 if (notFound) {
3503 ENTRY_UTIL::construct(d_entries_p + index,
3504 d_allocator_p,
3505 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3506 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3507 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3508 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3509 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05));
3510
3511 d_controls_p[index] = static_cast<bsl::uint8_t>(
3512 hashValue & k_HASHLET_MASK);
3513 ++d_size;
3514 }
3515
3516 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3517 d_controls_p + index,
3518 d_capacity - index - 1),
3519 notFound);
3520}
3521#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 5
3522
3523#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 6
3524template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3525template< class ARGS_01,
3526 class ARGS_02,
3527 class ARGS_03,
3528 class ARGS_04,
3529 class ARGS_05,
3530 class ARGS_06>
3531bsl::pair<typename
3532 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3533 bool>
3534FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3535 const KEY& key,
3536 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3537 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3538 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3539 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3540 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3541 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
3542{
3543 bool notFound;
3544 bsl::size_t hashValue = d_hasher(key);
3545 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3546
3547 if (notFound) {
3548 ENTRY_UTIL::construct(d_entries_p + index,
3549 d_allocator_p,
3550 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3551 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3552 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3553 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3554 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3555 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
3556
3557 d_controls_p[index] = static_cast<bsl::uint8_t>(
3558 hashValue & k_HASHLET_MASK);
3559 ++d_size;
3560 }
3561
3562 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3563 d_controls_p + index,
3564 d_capacity - index - 1),
3565 notFound);
3566}
3567#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 6
3568
3569#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 7
3570template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3571template< class ARGS_01,
3572 class ARGS_02,
3573 class ARGS_03,
3574 class ARGS_04,
3575 class ARGS_05,
3576 class ARGS_06,
3577 class ARGS_07>
3578bsl::pair<typename
3579 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3580 bool>
3581FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3582 const KEY& key,
3583 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3584 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3585 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3586 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3587 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3588 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3589 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
3590{
3591 bool notFound;
3592 bsl::size_t hashValue = d_hasher(key);
3593 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3594
3595 if (notFound) {
3596 ENTRY_UTIL::construct(d_entries_p + index,
3597 d_allocator_p,
3598 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3599 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3600 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3601 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3602 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3603 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3604 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
3605
3606 d_controls_p[index] = static_cast<bsl::uint8_t>(
3607 hashValue & k_HASHLET_MASK);
3608 ++d_size;
3609 }
3610
3611 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3612 d_controls_p + index,
3613 d_capacity - index - 1),
3614 notFound);
3615}
3616#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 7
3617
3618#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 8
3619template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3620template< class ARGS_01,
3621 class ARGS_02,
3622 class ARGS_03,
3623 class ARGS_04,
3624 class ARGS_05,
3625 class ARGS_06,
3626 class ARGS_07,
3627 class ARGS_08>
3628bsl::pair<typename
3629 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3630 bool>
3631FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3632 const KEY& key,
3633 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3634 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3635 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3636 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3637 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3638 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3639 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3640 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
3641{
3642 bool notFound;
3643 bsl::size_t hashValue = d_hasher(key);
3644 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3645
3646 if (notFound) {
3647 ENTRY_UTIL::construct(d_entries_p + index,
3648 d_allocator_p,
3649 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3650 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3651 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3652 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3653 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3654 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3655 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3656 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
3657
3658 d_controls_p[index] = static_cast<bsl::uint8_t>(
3659 hashValue & k_HASHLET_MASK);
3660 ++d_size;
3661 }
3662
3663 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3664 d_controls_p + index,
3665 d_capacity - index - 1),
3666 notFound);
3667}
3668#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 8
3669
3670#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 9
3671template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3672template< class ARGS_01,
3673 class ARGS_02,
3674 class ARGS_03,
3675 class ARGS_04,
3676 class ARGS_05,
3677 class ARGS_06,
3678 class ARGS_07,
3679 class ARGS_08,
3680 class ARGS_09>
3681bsl::pair<typename
3682 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3683 bool>
3684FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3685 const KEY& key,
3686 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3687 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3688 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3689 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3690 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3691 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3692 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3693 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
3694 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
3695{
3696 bool notFound;
3697 bsl::size_t hashValue = d_hasher(key);
3698 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3699
3700 if (notFound) {
3701 ENTRY_UTIL::construct(d_entries_p + index,
3702 d_allocator_p,
3703 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3704 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3705 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3706 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3707 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3708 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3709 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3710 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
3711 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
3712
3713 d_controls_p[index] = static_cast<bsl::uint8_t>(
3714 hashValue & k_HASHLET_MASK);
3715 ++d_size;
3716 }
3717
3718 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3719 d_controls_p + index,
3720 d_capacity - index - 1),
3721 notFound);
3722}
3723#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 9
3724
3725#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 10
3726template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3727template< class ARGS_01,
3728 class ARGS_02,
3729 class ARGS_03,
3730 class ARGS_04,
3731 class ARGS_05,
3732 class ARGS_06,
3733 class ARGS_07,
3734 class ARGS_08,
3735 class ARGS_09,
3736 class ARGS_10>
3737bsl::pair<typename
3738 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3739 bool>
3740FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3741 const KEY& key,
3742 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3743 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3744 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3745 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3746 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
3747 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
3748 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
3749 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
3750 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
3751 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
3752{
3753 bool notFound;
3754 bsl::size_t hashValue = d_hasher(key);
3755 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
3756
3757 if (notFound) {
3758 ENTRY_UTIL::construct(d_entries_p + index,
3759 d_allocator_p,
3760 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3761 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3762 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3763 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3764 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
3765 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
3766 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
3767 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
3768 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
3769 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
3770
3771 d_controls_p[index] = static_cast<bsl::uint8_t>(
3772 hashValue & k_HASHLET_MASK);
3773 ++d_size;
3774 }
3775
3776 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3777 d_controls_p + index,
3778 d_capacity - index - 1),
3779 notFound);
3780}
3781#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 10
3782
3783
3784#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 0
3785template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3786bsl::pair<typename
3787 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3788 bool>
3789FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3790 BloombergLP::bslmf::MovableRef<KEY> key)
3791{
3792 const KEY& k = key;
3793 bool notFound;
3794 bsl::size_t hashValue = d_hasher(k);
3795 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3796
3797 if (notFound) {
3798 ENTRY_UTIL::construct(d_entries_p + index,
3799 d_allocator_p);
3800
3801 d_controls_p[index] = static_cast<bsl::uint8_t>(
3802 hashValue & k_HASHLET_MASK);
3803 ++d_size;
3804 }
3805 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3806 d_controls_p + index,
3807 d_capacity - index - 1),
3808 notFound);
3809}
3810#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 0
3811
3812#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 1
3813template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3814template< class ARGS_01>
3815bsl::pair<typename
3816 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3817 bool>
3818FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3819 BloombergLP::bslmf::MovableRef<KEY> key,
3820 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01)
3821{
3822 const KEY& k = key;
3823 bool notFound;
3824 bsl::size_t hashValue = d_hasher(k);
3825 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3826
3827 if (notFound) {
3828 ENTRY_UTIL::construct(d_entries_p + index,
3829 d_allocator_p,
3830 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01));
3831
3832 d_controls_p[index] = static_cast<bsl::uint8_t>(
3833 hashValue & k_HASHLET_MASK);
3834 ++d_size;
3835 }
3836 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3837 d_controls_p + index,
3838 d_capacity - index - 1),
3839 notFound);
3840}
3841#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 1
3842
3843#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 2
3844template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3845template< class ARGS_01,
3846 class ARGS_02>
3847bsl::pair<typename
3848 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3849 bool>
3850FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3851 BloombergLP::bslmf::MovableRef<KEY> key,
3852 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3853 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02)
3854{
3855 const KEY& k = key;
3856 bool notFound;
3857 bsl::size_t hashValue = d_hasher(k);
3858 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3859
3860 if (notFound) {
3861 ENTRY_UTIL::construct(d_entries_p + index,
3862 d_allocator_p,
3863 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3864 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02));
3865
3866 d_controls_p[index] = static_cast<bsl::uint8_t>(
3867 hashValue & k_HASHLET_MASK);
3868 ++d_size;
3869 }
3870 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3871 d_controls_p + index,
3872 d_capacity - index - 1),
3873 notFound);
3874}
3875#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 2
3876
3877#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 3
3878template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3879template< class ARGS_01,
3880 class ARGS_02,
3881 class ARGS_03>
3882bsl::pair<typename
3883 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3884 bool>
3885FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3886 BloombergLP::bslmf::MovableRef<KEY> key,
3887 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3888 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3889 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03)
3890{
3891 const KEY& k = key;
3892 bool notFound;
3893 bsl::size_t hashValue = d_hasher(k);
3894 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3895
3896 if (notFound) {
3897 ENTRY_UTIL::construct(d_entries_p + index,
3898 d_allocator_p,
3899 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3900 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3901 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03));
3902
3903 d_controls_p[index] = static_cast<bsl::uint8_t>(
3904 hashValue & k_HASHLET_MASK);
3905 ++d_size;
3906 }
3907 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3908 d_controls_p + index,
3909 d_capacity - index - 1),
3910 notFound);
3911}
3912#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 3
3913
3914#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 4
3915template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3916template< class ARGS_01,
3917 class ARGS_02,
3918 class ARGS_03,
3919 class ARGS_04>
3920bsl::pair<typename
3921 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3922 bool>
3923FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3924 BloombergLP::bslmf::MovableRef<KEY> key,
3925 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3926 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3927 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3928 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04)
3929{
3930 const KEY& k = key;
3931 bool notFound;
3932 bsl::size_t hashValue = d_hasher(k);
3933 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3934
3935 if (notFound) {
3936 ENTRY_UTIL::construct(d_entries_p + index,
3937 d_allocator_p,
3938 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3939 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3940 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3941 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04));
3942
3943 d_controls_p[index] = static_cast<bsl::uint8_t>(
3944 hashValue & k_HASHLET_MASK);
3945 ++d_size;
3946 }
3947 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3948 d_controls_p + index,
3949 d_capacity - index - 1),
3950 notFound);
3951}
3952#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 4
3953
3954#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 5
3955template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3956template< class ARGS_01,
3957 class ARGS_02,
3958 class ARGS_03,
3959 class ARGS_04,
3960 class ARGS_05>
3961bsl::pair<typename
3962 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
3963 bool>
3964FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
3965 BloombergLP::bslmf::MovableRef<KEY> key,
3966 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
3967 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
3968 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
3969 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
3970 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05)
3971{
3972 const KEY& k = key;
3973 bool notFound;
3974 bsl::size_t hashValue = d_hasher(k);
3975 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
3976
3977 if (notFound) {
3978 ENTRY_UTIL::construct(d_entries_p + index,
3979 d_allocator_p,
3980 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
3981 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
3982 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
3983 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
3984 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05));
3985
3986 d_controls_p[index] = static_cast<bsl::uint8_t>(
3987 hashValue & k_HASHLET_MASK);
3988 ++d_size;
3989 }
3990 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
3991 d_controls_p + index,
3992 d_capacity - index - 1),
3993 notFound);
3994}
3995#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 5
3996
3997#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 6
3998template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
3999template< class ARGS_01,
4000 class ARGS_02,
4001 class ARGS_03,
4002 class ARGS_04,
4003 class ARGS_05,
4004 class ARGS_06>
4005bsl::pair<typename
4006 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4007 bool>
4008FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4009 BloombergLP::bslmf::MovableRef<KEY> key,
4010 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
4011 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
4012 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
4013 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
4014 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
4015 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06)
4016{
4017 const KEY& k = key;
4018 bool notFound;
4019 bsl::size_t hashValue = d_hasher(k);
4020 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
4021
4022 if (notFound) {
4023 ENTRY_UTIL::construct(d_entries_p + index,
4024 d_allocator_p,
4025 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
4026 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
4027 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
4028 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
4029 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
4030 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06));
4031
4032 d_controls_p[index] = static_cast<bsl::uint8_t>(
4033 hashValue & k_HASHLET_MASK);
4034 ++d_size;
4035 }
4036 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4037 d_controls_p + index,
4038 d_capacity - index - 1),
4039 notFound);
4040}
4041#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 6
4042
4043#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 7
4044template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4045template< class ARGS_01,
4046 class ARGS_02,
4047 class ARGS_03,
4048 class ARGS_04,
4049 class ARGS_05,
4050 class ARGS_06,
4051 class ARGS_07>
4052bsl::pair<typename
4053 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4054 bool>
4055FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4056 BloombergLP::bslmf::MovableRef<KEY> key,
4057 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
4058 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
4059 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
4060 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
4061 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
4062 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
4063 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07)
4064{
4065 const KEY& k = key;
4066 bool notFound;
4067 bsl::size_t hashValue = d_hasher(k);
4068 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
4069
4070 if (notFound) {
4071 ENTRY_UTIL::construct(d_entries_p + index,
4072 d_allocator_p,
4073 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
4074 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
4075 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
4076 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
4077 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
4078 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
4079 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07));
4080
4081 d_controls_p[index] = static_cast<bsl::uint8_t>(
4082 hashValue & k_HASHLET_MASK);
4083 ++d_size;
4084 }
4085 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4086 d_controls_p + index,
4087 d_capacity - index - 1),
4088 notFound);
4089}
4090#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 7
4091
4092#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 8
4093template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4094template< class ARGS_01,
4095 class ARGS_02,
4096 class ARGS_03,
4097 class ARGS_04,
4098 class ARGS_05,
4099 class ARGS_06,
4100 class ARGS_07,
4101 class ARGS_08>
4102bsl::pair<typename
4103 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4104 bool>
4105FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4106 BloombergLP::bslmf::MovableRef<KEY> key,
4107 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
4108 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
4109 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
4110 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
4111 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
4112 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
4113 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
4114 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08)
4115{
4116 const KEY& k = key;
4117 bool notFound;
4118 bsl::size_t hashValue = d_hasher(k);
4119 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
4120
4121 if (notFound) {
4122 ENTRY_UTIL::construct(d_entries_p + index,
4123 d_allocator_p,
4124 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
4125 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
4126 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
4127 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
4128 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
4129 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
4130 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
4131 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08));
4132
4133 d_controls_p[index] = static_cast<bsl::uint8_t>(
4134 hashValue & k_HASHLET_MASK);
4135 ++d_size;
4136 }
4137 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4138 d_controls_p + index,
4139 d_capacity - index - 1),
4140 notFound);
4141}
4142#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 8
4143
4144#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 9
4145template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4146template< class ARGS_01,
4147 class ARGS_02,
4148 class ARGS_03,
4149 class ARGS_04,
4150 class ARGS_05,
4151 class ARGS_06,
4152 class ARGS_07,
4153 class ARGS_08,
4154 class ARGS_09>
4155bsl::pair<typename
4156 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4157 bool>
4158FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4159 BloombergLP::bslmf::MovableRef<KEY> key,
4160 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
4161 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
4162 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
4163 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
4164 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
4165 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
4166 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
4167 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
4168 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09)
4169{
4170 const KEY& k = key;
4171 bool notFound;
4172 bsl::size_t hashValue = d_hasher(k);
4173 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
4174
4175 if (notFound) {
4176 ENTRY_UTIL::construct(d_entries_p + index,
4177 d_allocator_p,
4178 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
4179 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
4180 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
4181 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
4182 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
4183 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
4184 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
4185 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
4186 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09));
4187
4188 d_controls_p[index] = static_cast<bsl::uint8_t>(
4189 hashValue & k_HASHLET_MASK);
4190 ++d_size;
4191 }
4192 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4193 d_controls_p + index,
4194 d_capacity - index - 1),
4195 notFound);
4196}
4197#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 9
4198
4199#if BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 10
4200template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4201template< class ARGS_01,
4202 class ARGS_02,
4203 class ARGS_03,
4204 class ARGS_04,
4205 class ARGS_05,
4206 class ARGS_06,
4207 class ARGS_07,
4208 class ARGS_08,
4209 class ARGS_09,
4210 class ARGS_10>
4211bsl::pair<typename
4212 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4213 bool>
4214FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4215 BloombergLP::bslmf::MovableRef<KEY> key,
4216 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01,
4217 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02,
4218 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_03) args_03,
4219 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_04) args_04,
4220 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_05) args_05,
4221 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_06) args_06,
4222 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_07) args_07,
4223 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_08) args_08,
4224 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_09) args_09,
4225 BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_10) args_10)
4226{
4227 const KEY& k = key;
4228 bool notFound;
4229 bsl::size_t hashValue = d_hasher(k);
4230 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
4231
4232 if (notFound) {
4233 ENTRY_UTIL::construct(d_entries_p + index,
4234 d_allocator_p,
4235 BSLS_COMPILERFEATURES_FORWARD(ARGS_01, args_01),
4236 BSLS_COMPILERFEATURES_FORWARD(ARGS_02, args_02),
4237 BSLS_COMPILERFEATURES_FORWARD(ARGS_03, args_03),
4238 BSLS_COMPILERFEATURES_FORWARD(ARGS_04, args_04),
4239 BSLS_COMPILERFEATURES_FORWARD(ARGS_05, args_05),
4240 BSLS_COMPILERFEATURES_FORWARD(ARGS_06, args_06),
4241 BSLS_COMPILERFEATURES_FORWARD(ARGS_07, args_07),
4242 BSLS_COMPILERFEATURES_FORWARD(ARGS_08, args_08),
4243 BSLS_COMPILERFEATURES_FORWARD(ARGS_09, args_09),
4244 BSLS_COMPILERFEATURES_FORWARD(ARGS_10, args_10));
4245
4246 d_controls_p[index] = static_cast<bsl::uint8_t>(
4247 hashValue & k_HASHLET_MASK);
4248 ++d_size;
4249 }
4250 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4251 d_controls_p + index,
4252 d_capacity - index - 1),
4253 notFound);
4254}
4255#endif // BDLC_FLATHASHTABLE_VARIADIC_LIMIT_F >= 10
4256
4257#else
4258// The generated code below is a workaround for the absence of perfect
4259// forwarding in some compilers.
4260template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4261template< class... ARGS>
4262bsl::pair<typename
4263 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4264 bool>
4265FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4266 const KEY& key,
4268{
4269 bool notFound;
4270 bsl::size_t hashValue = d_hasher(key);
4271 bsl::size_t index = indexOfKey(&notFound, key, hashValue);
4272
4273 if (notFound) {
4274 ENTRY_UTIL::construct(d_entries_p + index,
4275 d_allocator_p,
4276 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
4277
4278 d_controls_p[index] = static_cast<bsl::uint8_t>(
4279 hashValue & k_HASHLET_MASK);
4280 ++d_size;
4281 }
4282
4283 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4284 d_controls_p + index,
4285 d_capacity - index - 1),
4286 notFound);
4287}
4288
4289template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4290template< class... ARGS>
4291bsl::pair<typename
4292 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator,
4293 bool>
4294FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::try_emplace(
4295 BloombergLP::bslmf::MovableRef<KEY> key,
4297{
4298 const KEY& k = key;
4299 bool notFound;
4300 bsl::size_t hashValue = d_hasher(k);
4301 bsl::size_t index = indexOfKey(&notFound, k, hashValue);
4302
4303 if (notFound) {
4304 ENTRY_UTIL::construct(d_entries_p + index,
4305 d_allocator_p,
4306 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
4307
4308 d_controls_p[index] = static_cast<bsl::uint8_t>(
4309 hashValue & k_HASHLET_MASK);
4310 ++d_size;
4311 }
4312 return bsl::pair<iterator, bool>(IteratorImp(d_entries_p + index,
4313 d_controls_p + index,
4314 d_capacity - index - 1),
4315 notFound);
4316}
4317// }}} END GENERATED CODE
4318#endif
4319
4320 // Iterators
4321
4322template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4323inline
4324typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
4325FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::begin()
4326{
4327 if (d_size) {
4328 for (bsl::size_t i = 0; i < d_capacity; ++i) {
4329 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
4330 return iterator(IteratorImp(d_entries_p + i,
4331 d_controls_p + i,
4332 d_capacity - i - 1)); // RETURN
4333 }
4334 }
4335 }
4336 return iterator();
4337}
4338
4339template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4340inline
4341typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::iterator
4342FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::end()
4343{
4344 return iterator();
4345}
4346
4347 // Aspects
4348
4349template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4350inline
4351void FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::swap(
4352 FlatHashTable& other)
4353{
4354 BSLS_ASSERT_SAFE(allocator() == other.allocator());
4355
4356 bslalg::SwapUtil::swap(&d_entries_p, &other.d_entries_p);
4357 bslalg::SwapUtil::swap(&d_controls_p, &other.d_controls_p);
4358 bslalg::SwapUtil::swap(&d_size, &other.d_size);
4359 bslalg::SwapUtil::swap(&d_capacity, &other.d_capacity);
4360 bslalg::SwapUtil::swap(&d_groupControlShift, &other.d_groupControlShift);
4361 bslalg::SwapUtil::swap(&d_hasher, &other.d_hasher);
4362 bslalg::SwapUtil::swap(&d_equal, &other.d_equal);
4363}
4364
4365// ACCESSORS
4366template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4367inline
4368bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::
4369 capacity() const
4370{
4371 return d_capacity;
4372}
4373
4374template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4375inline
4376bool FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::contains(
4377 const KEY& key) const
4378{
4379 return find(key) != end();
4380}
4381
4382template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4383inline
4384const bsl::uint8_t *FlatHashTable<KEY,
4385 ENTRY,
4386 ENTRY_UTIL,
4387 HASH,
4388 EQUAL>::controls() const
4389{
4390 return d_controls_p;
4391}
4392
4393template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4394inline
4395bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::count(
4396 const KEY& key) const
4397{
4398 return contains(key) ? 1 : 0;
4399}
4400
4401template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4402inline
4403bool FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::empty() const
4404{
4405 return 0 == d_size;
4406}
4407
4408template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4409inline
4410const ENTRY *FlatHashTable<KEY,
4411 ENTRY,
4412 ENTRY_UTIL,
4413 HASH,
4414 EQUAL>::entries() const
4415{
4416 return d_entries_p;
4417}
4418
4419template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4420inline
4421bsl::pair<typename FlatHashTable<KEY,
4422 ENTRY,
4423 ENTRY_UTIL,
4424 HASH,
4425 EQUAL>::const_iterator,
4426 typename FlatHashTable<KEY,
4427 ENTRY,
4428 ENTRY_UTIL,
4429 HASH,
4430 EQUAL>::const_iterator>
4431FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::equal_range(
4432 const KEY& key) const
4433{
4434 const_iterator cit1 = find(key);
4435 const_iterator cit2 = cit1;
4436 if (cit1 != end()) {
4437 ++cit2;
4438 }
4439 return bsl::make_pair(cit1, cit2);
4440}
4441
4442template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4443inline
4444typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
4445FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::find(const KEY& key) const
4446{
4447 bsl::size_t index = findKey(key, d_hasher(key));
4448 if (index < d_capacity) {
4449 return const_iterator(IteratorImp(d_entries_p + index,
4450 d_controls_p + index,
4451 d_capacity - index - 1)); // RETURN
4452 }
4453 return end();
4454}
4455
4456template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4457inline
4458HASH FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::hash_function() const
4459{
4460 return d_hasher;
4461}
4462
4463template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4464inline
4465EQUAL FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::key_eq() const
4466{
4467 return d_equal;
4468}
4469
4470template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4471inline
4472float bdlc::FlatHashTable<KEY,
4473 ENTRY,
4474 ENTRY_UTIL,
4475 HASH,
4476 EQUAL>::load_factor() const
4477{
4478 return d_capacity > 0
4479 ? static_cast<float>(d_size) / static_cast<float>(d_capacity)
4480 : 0;
4481}
4482
4483template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4484inline
4485float bdlc::FlatHashTable<KEY,
4486 ENTRY,
4487 ENTRY_UTIL,
4488 HASH,
4489 EQUAL>::max_load_factor() const
4490{
4491 return static_cast<float>(k_MAX_LOAD_FACTOR_NUMERATOR)
4492 / static_cast<float>(k_MAX_LOAD_FACTOR_DENOMINATOR);
4493}
4494
4495template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4496inline
4497bsl::size_t FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::size() const
4498{
4499 return d_size;
4500}
4501
4502 // Iterators
4503
4504template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4505inline
4506typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
4507FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::begin() const
4508{
4509 if (d_size) {
4510 for (bsl::size_t i = 0; i < d_capacity; ++i) {
4511 if (0 == (d_controls_p[i] & GroupControl::k_EMPTY)) {
4512 return const_iterator(
4513 IteratorImp(d_entries_p + i,
4514 d_controls_p + i,
4515 d_capacity - i - 1)); // RETURN
4516 }
4517 }
4518 }
4519 return const_iterator();
4520}
4521
4522template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4523inline
4524typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
4525FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::cbegin() const
4526{
4527 return begin();
4528}
4529
4530template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4531inline
4532typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
4533FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::cend() const
4534{
4535 return end();
4536}
4537
4538template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4539inline
4540typename FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::const_iterator
4541FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::end() const
4542{
4543 return const_iterator();
4544}
4545
4546 // Aspects
4547
4548template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4549inline
4550bslma::Allocator *FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>::
4551 allocator() const
4552{
4553 return d_allocator_p;
4554}
4555
4556} // close package namespace
4557
4558// FREE OPERATORS
4559template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4560bool bdlc::operator==(const FlatHashTable<KEY,
4561 ENTRY,
4562 ENTRY_UTIL,
4563 HASH,
4564 EQUAL>& lhs,
4565 const FlatHashTable<KEY,
4566 ENTRY,
4567 ENTRY_UTIL,
4568 HASH,
4569 EQUAL>& rhs)
4570{
4571 typedef typename FlatHashTable<KEY,
4572 ENTRY,
4573 ENTRY_UTIL,
4574 HASH,
4575 EQUAL>::const_iterator ConstIterator;
4576
4577 if (lhs.size() == rhs.size()) {
4578 ConstIterator lhsEnd = lhs.end();
4579 ConstIterator rhsEnd = rhs.end();
4580
4581 if (lhs.capacity() <= rhs.capacity()) {
4582 for (ConstIterator it = lhs.begin(); it != lhsEnd; ++it) {
4583 ConstIterator i = rhs.find(ENTRY_UTIL::key(*it));
4584 if (i == rhsEnd || *i != *it) {
4585 return false; // RETURN
4586 }
4587 }
4588 return true; // RETURN
4589 }
4590 else {
4591 for (ConstIterator it = rhs.begin(); it != rhsEnd; ++it) {
4592 ConstIterator i = lhs.find(ENTRY_UTIL::key(*it));
4593 if (i == lhsEnd || *i != *it) {
4594 return false; // RETURN
4595 }
4596 }
4597 return true; // RETURN
4598 }
4599 }
4600 return false;
4601}
4602
4603template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4604bool bdlc::operator!=(const FlatHashTable<KEY,
4605 ENTRY,
4606 ENTRY_UTIL,
4607 HASH,
4608 EQUAL>& lhs,
4609 const FlatHashTable<KEY,
4610 ENTRY,
4611 ENTRY_UTIL,
4612 HASH,
4613 EQUAL>& rhs)
4614{
4615 return !(lhs == rhs);
4616}
4617
4618// FREE FUNCTIONS
4619template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4620inline
4621void bdlc::swap(FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& a,
4622 FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL>& b)
4623{
4624 if (a.allocator() == b.allocator()) {
4625 a.swap(b);
4626
4627 return; // RETURN
4628 }
4629
4630 typedef FlatHashTable<KEY, ENTRY, ENTRY_UTIL, HASH, EQUAL> Table;
4631
4632 Table futureA(b, a.allocator());
4633 Table futureB(a, b.allocator());
4634
4635 futureA.swap(a);
4636 futureB.swap(b);
4637}
4638
4639namespace bslma {
4640
4641template <class KEY, class ENTRY, class ENTRY_UTIL, class HASH, class EQUAL>
4642struct UsesBslmaAllocator<bdlc::FlatHashTable<KEY,
4643 ENTRY,
4644 ENTRY_UTIL,
4645 HASH,
4646 EQUAL> > : bsl::true_type {
4647};
4648
4649} // close namespace bslma
4650
4651namespace bdlc {
4652
4653 // -----------------------------
4654 // struct FlatHashTable_ImplUtil
4655 // -----------------------------
4656
4657// PRIVATE CLASS METHODS
4658template <class ENTRY_TYPE>
4659inline
4660void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
4661 ENTRY_TYPE *firstDestinationEntry,
4662 bsl::uint8_t *firstDestinationControl,
4663 const ENTRY_TYPE *firstSourceEntry,
4664 const ENTRY_TYPE *lastSourceEntry,
4665 const bsl::uint8_t *firstSourceControl,
4666 const bsl::uint8_t *lastSourceControl,
4667 bslma::Allocator *entryAllocator,
4668 bsl::false_type isBitwiseCopyable)
4669{
4670 (void) isBitwiseCopyable;
4671
4673
4674 bsl::memcpy(firstDestinationControl,
4675 firstSourceControl,
4676 bsl::distance(firstSourceControl, lastSourceControl) *
4677 sizeof(bsl::uint8_t));
4678
4679 const bsl::size_t numEntries = static_cast<bsl::size_t>(
4680 bsl::distance(firstSourceEntry, lastSourceEntry));
4681
4682 DestroyEntryArrayProctor<ENTRY_TYPE> destroyEntriesProctor(
4683 firstDestinationEntry,
4684 firstDestinationEntry,
4685 firstDestinationControl,
4686 firstDestinationControl);
4687
4688 for (bsl::size_t idx = 0; idx != numEntries; ++idx) {
4689 ENTRY_TYPE& destinationEntry = *(firstDestinationEntry + idx);
4690 const bsl::uint8_t& sourceControl = *(firstSourceControl + idx);
4691 const ENTRY_TYPE& sourceEntry = *(firstSourceEntry + idx);
4692
4693 if (0 == (sourceControl & GroupControl::k_EMPTY)) {
4695 &destinationEntry, entryAllocator, sourceEntry);
4696 }
4697
4698 destroyEntriesProctor.moveEnd(1);
4699 }
4700
4701 destroyEntriesProctor.release();
4702}
4703
4704template <class ENTRY_TYPE>
4705inline
4706void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
4707 ENTRY_TYPE *firstDestinationEntry,
4708 bsl::uint8_t *firstDestinationControl,
4709 const ENTRY_TYPE *firstSourceEntry,
4710 const ENTRY_TYPE *lastSourceEntry,
4711 const bsl::uint8_t *firstSourceControl,
4712 const bsl::uint8_t *lastSourceControl,
4714 bsl::true_type isBitwiseCopyable)
4715{
4716 (void) isBitwiseCopyable;
4717
4719
4720 bsl::memcpy(firstDestinationControl,
4721 firstSourceControl,
4722 bsl::distance(firstSourceControl, lastSourceControl) *
4723 sizeof(bsl::uint8_t));
4724
4725#if defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000
4726#pragma GCC diagnostic push
4727#pragma GCC diagnostic ignored "-Wclass-memaccess"
4728#endif
4729
4730 bsl::memcpy(firstDestinationEntry,
4731 firstSourceEntry,
4732 bsl::distance(firstSourceEntry, lastSourceEntry) *
4733 sizeof(ENTRY_TYPE));
4734
4735#if defined(BSLS_PLATFORM_CMP_GNU) && BSLS_PLATFORM_CMP_VERSION >= 80000
4736#pragma GCC diagnostic pop
4737#endif
4738}
4739
4740template <class ENTRY_TYPE>
4741inline
4742void FlatHashTable_ImplUtil::destroyEntryArray(
4743 ENTRY_TYPE *firstEntry,
4744 ENTRY_TYPE *lastEntry,
4745 const bsl::uint8_t *firstControl,
4746 const bsl::uint8_t *lastControl,
4747 bsl::false_type triviallyDestructible)
4748{
4749 (void) triviallyDestructible;
4750
4751 ///Implementation Note
4752 ///-------------------
4753 // The implementation of this function uses the
4754 // 'FlatHashTable_GroupControl' facilities to bulk search through the
4755 // control range and look for entries that need to be destroyed. However,
4756 // the size of the ranges passed to this function are not always a multiple
4757 // of 'GroupControl::k_SIZE', and so a second loop is needed to
4758 // sequentially destroy the up-to 'GroupControl::k_SIZE - 1' number of
4759 // entries that cannot be destroyed as part of a bulk operation on
4760 // 'GroupControl::k_SIZE' elements of the entry range.
4761 //
4762 // It may be surprising that the size of these ranges is not always a
4763 // multiple of 'GroupControl::k_SIZE' despite the fact that the capacity of
4764 // a 'FlatHashTable' is always a power of 2. However, this operation can
4765 // be invoked midway through copying one entry array to another if copying
4766 // an entry throws and the already-copied elements need to then be
4767 // destroyed as part of cleaning up during exception handling.
4768
4769 static_cast<void>(lastControl); // silence unused variable warnings
4770
4771 const bsl::size_t numEntries =
4772 static_cast<bsl::size_t>(bsl::distance(firstEntry, lastEntry));
4773 const bsl::size_t numGroupedEntries =
4774 numEntries - (numEntries % GroupControl::k_SIZE);
4775
4776 for (bsl::size_t idx = 0;
4777 idx != numGroupedEntries;
4778 idx += GroupControl::k_SIZE) {
4779 GroupControl groupControl(firstControl + idx);
4780 bsl::uint32_t candidates = groupControl.inUse();
4781 while (candidates) {
4782 const int offset = bdlb::BitUtil::numTrailingUnsetBits(candidates);
4783 bslma::DestructionUtil::destroy(firstEntry + idx + offset);
4784 candidates = bdlb::BitUtil::withBitCleared(candidates, offset);
4785 }
4786 }
4787
4788 for (bsl::size_t idx = numGroupedEntries; idx != numEntries; ++idx) {
4789 ENTRY_TYPE& entry = *(firstEntry + idx);
4790 const bsl::uint8_t& control = *(firstControl + idx);
4791
4792 if (0 == (control & GroupControl::k_EMPTY)) {
4793 bslma::DestructionUtil::destroy(&entry);
4794 }
4795 }
4796}
4797
4798template <class ENTRY_TYPE>
4799inline
4800void FlatHashTable_ImplUtil::destroyEntryArray(
4801 ENTRY_TYPE *,
4802 ENTRY_TYPE *,
4803 const bsl::uint8_t *,
4804 const bsl::uint8_t *,
4805 bsl::true_type triviallyDestructible)
4806{
4807 (void) triviallyDestructible;
4808
4809 // Do nothing, in just the right way.
4810}
4811
4812// CLASS METHODS
4813template <class ENTRY_TYPE>
4814inline
4815void FlatHashTable_ImplUtil::copyEntryAndControlArrays(
4816 ENTRY_TYPE *firstDestinationEntry,
4817 bsl::uint8_t *firstDestinationControl,
4818 const ENTRY_TYPE *firstSourceEntry,
4819 const ENTRY_TYPE *lastSourceEntry,
4820 const bsl::uint8_t *firstSourceControl,
4821 const bsl::uint8_t *lastSourceControl,
4822 bslma::Allocator *entryAllocator)
4823{
4824 BSLS_ASSERT_SAFE(bsl::distance(firstSourceEntry, lastSourceEntry) ==
4825 bsl::distance(firstSourceControl, lastSourceControl));
4826
4827 FlatHashTable_ImplUtil::copyEntryAndControlArrays(
4828 firstDestinationEntry,
4829 firstDestinationControl,
4830 firstSourceEntry,
4831 lastSourceEntry,
4832 firstSourceControl,
4833 lastSourceControl,
4834 entryAllocator,
4836}
4837
4838template <class ENTRY_TYPE>
4839inline
4840void FlatHashTable_ImplUtil::destroyEntryArray(
4841 ENTRY_TYPE *firstEntry,
4842 ENTRY_TYPE *lastEntry,
4843 const bsl::uint8_t *firstControl,
4844 const bsl::uint8_t *lastControl)
4845{
4846 BSLS_ASSERT_SAFE(bsl::distance(firstEntry, lastEntry) ==
4847 bsl::distance(firstControl, lastControl));
4848
4849 ///Implementation Note
4850 ///-------------------
4851 // If a type is trivially copyable then it is also trivially destructible.
4852 // The type trait 'bslmf::IsTriviallyCopyable' is available in C++03
4853 // mode and later, however 'bsl::is_trivially_destructible' is only
4854 // available in C++11 and later and not always on clang. So, this utility
4855 // 'struct' uses bitwise copyability as a stand-in for trivial
4856 // destructibility in order to provide certain optimizations uniformly
4857 // across all C++ versions.
4858
4860 IsEntryTypeTriviallyDestructible;
4861
4862 FlatHashTable_ImplUtil::destroyEntryArray(
4863 firstEntry,
4864 lastEntry,
4865 firstControl,
4866 lastControl,
4867 IsEntryTypeTriviallyDestructible());
4868}
4869
4870 // ------------------------------------------------------
4871 // class FlatHashTable_ImplUtil::DestroyEntryArrayProctor
4872 // ------------------------------------------------------
4873
4874// CREATORS
4875template <class ENTRY_TYPE>
4876inline
4877FlatHashTable_ImplUtil::DestroyEntryArrayProctor<
4878 ENTRY_TYPE>::DestroyEntryArrayProctor(ENTRY_TYPE *firstEntry,
4879 ENTRY_TYPE *lastEntry,
4880 const bsl::uint8_t *firstControl,
4881 const bsl::uint8_t *lastControl)
4882: d_firstEntry_p(firstEntry)
4883, d_lastEntry_p(lastEntry)
4884, d_firstControl_p(firstControl)
4885, d_lastControl_p(lastControl)
4886{
4887}
4888
4889template <class ENTRY_TYPE>
4890inline
4891FlatHashTable_ImplUtil::DestroyEntryArrayProctor<
4892 ENTRY_TYPE>::~DestroyEntryArrayProctor()
4893{
4894 ImplUtil::destroyEntryArray(d_firstEntry_p,
4895 d_lastEntry_p,
4896 d_firstControl_p,
4897 d_lastControl_p);
4898}
4899
4900// MANIPULATORS
4901template <class ENTRY_TYPE>
4902inline
4903void FlatHashTable_ImplUtil::DestroyEntryArrayProctor<ENTRY_TYPE>::moveEnd(
4904 bsl::ptrdiff_t offset)
4905{
4906 d_lastEntry_p += offset;
4907 d_lastControl_p += offset;
4908}
4909
4910template <class ENTRY_TYPE>
4911inline
4912void FlatHashTable_ImplUtil::DestroyEntryArrayProctor<ENTRY_TYPE>::release()
4913{
4914 d_firstEntry_p = 0;
4915 d_lastEntry_p = 0;
4916 d_firstControl_p = 0;
4917 d_lastControl_p = 0;
4918}
4919
4920} // close package namespace
4921
4922
4923#else // if ! defined(DEFINED_BDLC_FLATHASHTABLE_H)
4924# error Not valid except when included from bdlc_flathashtable.h
4925#endif // ! defined(COMPILING_BDLC_FLATHASHTABLE_H)
4926
4927#endif // ! defined(INCLUDED_BDLC_FLATHASHTABLE_CPP03)
4928
4929// ----------------------------------------------------------------------------
4930// Copyright 2020 Bloomberg Finance L.P.
4931// Copyright 2018 The Abseil Authors
4932//
4933// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4934// use this file except in compliance with the License. You may obtain a copy
4935// of the License at
4936//
4937// http://www.apache.org/licenses/LICENSE-2.0
4938//
4939// Unless required by applicable law or agreed to in writing, software
4940// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
4941// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
4942// License for the specific language governing permissions and limitations
4943// under the License.
4944// ----------------------------- END-OF-FILE ----------------------------------
4945
4946/** @} */
4947/** @} */
4948/** @} */
static const bsl::uint8_t k_EMPTY
Definition bdlc_flathashtable_groupcontrol.h:125
static const bsl::size_t k_SIZE
Definition bdlc_flathashtable_groupcontrol.h:127
FlatHashTable_IteratorImp & operator=(const FlatHashTable_IteratorImp &rhs)
Definition bdlc_flathashtable.h:1376
FlatHashTable_IteratorImp()
Definition bdlc_flathashtable.h:1344
void operator++()
Definition bdlc_flathashtable.h:1388
ENTRY & operator*() const
Definition bdlc_flathashtable.h:1409
Definition bdlc_flathashtable.h:326
void clear()
Definition bdlc_flathashtable.h:1875
bsl::size_t erase(const KEY &key)
Definition bdlc_flathashtable.h:1927
const ENTRY * entries() const
Definition bdlc_flathashtable.h:2329
static const bsl::size_t k_MIN_CAPACITY
Definition bdlc_flathashtable.h:503
float max_load_factor() const
Definition bdlc_flathashtable.h:2404
const_iterator cbegin() const
Definition bdlc_flathashtable.h:2440
void swap(FlatHashTable &other)
Definition bdlc_flathashtable.h:2266
HASH hash_type
Definition bdlc_flathashtable.h:337
bsl::pair< iterator, bool > insert(const ENTRY &entry)
Definition bdlc_flathashtable.h:2050
EQUAL key_equal_type
Definition bdlc_flathashtable.h:338
static const bsl::size_t k_MAX_LOAD_FACTOR_NUMERATOR
Definition bdlc_flathashtable.h:508
void reset()
Definition bdlc_flathashtable.h:2154
bsl::pair< iterator, bool > emplace(ARGS &&... args)
iterator find(const KEY &key)
Definition bdlc_flathashtable.h:2036
iterator end()
Definition bdlc_flathashtable.h:2257
bool empty() const
Definition bdlc_flathashtable.h:2318
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:513
ENTRY_UTIL entry_util_type
Definition bdlc_flathashtable.h:336
static const bsl::int8_t k_HASHLET_MASK
Definition bdlc_flathashtable.h:506
bslma::Allocator * allocator() const
Return the allocator used by this hash table to supply memory.
Definition bdlc_flathashtable.h:2466
bsl::size_t capacity() const
Definition bdlc_flathashtable.h:2284
bslstl::ForwardIterator< const ENTRY, IteratorImp > const_iterator
Definition bdlc_flathashtable.h:343
bslstl::ForwardIterator< ENTRY, IteratorImp > iterator
Definition bdlc_flathashtable.h:341
const bsl::uint8_t * controls() const
Definition bdlc_flathashtable.h:2303
ENTRY entry_type
Definition bdlc_flathashtable.h:335
ENTRY & operator[](BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) key)
Definition bdlc_flathashtable.h:1852
KEY key_type
Definition bdlc_flathashtable.h:334
EQUAL key_eq() const
Definition bdlc_flathashtable.h:2380
bool contains(const KEY &key) const
Definition bdlc_flathashtable.h:2291
iterator begin()
Definition bdlc_flathashtable.h:2240
void reserve(bsl::size_t numEntries)
Definition bdlc_flathashtable.h:2135
bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate< HASH, LOOKUP_KEY >::value &&BloombergLP::bslmf::IsTransparentPredicate< EQUAL, LOOKUP_KEY >::value, bsl::pair< iterator, bool > >::type insertTransparent(LOOKUP_KEY &&key)
Definition bdlc_flathashtable.h:754
const_iterator cend() const
Definition bdlc_flathashtable.h:2448
bsl::size_t size() const
Return the number of entries in this table.
Definition bdlc_flathashtable.h:2412
bsl::size_t count(const KEY &key) const
Definition bdlc_flathashtable.h:2310
FlatHashTable & operator=(const FlatHashTable &rhs)
Definition bdlc_flathashtable.h:1824
~FlatHashTable()
Destroy this object and each of its entries.
Definition bdlc_flathashtable.h:1800
HASH hash_function() const
Definition bdlc_flathashtable.h:2373
float load_factor() const
Definition bdlc_flathashtable.h:2391
void rehash(bsl::size_t minimumCapacity)
Definition bdlc_flathashtable.h:2114
bsl::pair< iterator, iterator > equal_range(const KEY &key)
Definition bdlc_flathashtable.h:1894
Definition bslstl_pair.h:1280
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:182
Definition bslma_allocator.h:545
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:752
Definition bslstl_forwarditerator.h:171
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1917
#define BSLS_ASSERT_OPT_UNREACHABLE(X)
Definition bsls_assert.h:2065
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2343
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2349
#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:506
void swap(BitArray &a, BitArray &b)
bool operator==(const BitArray &lhs, const BitArray &rhs)
bool operator!=(const BitArray &lhs, const BitArray &rhs)
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
deque< VALUE_TYPE, ALLOCATOR >::size_type erase(deque< VALUE_TYPE, ALLOCATOR > &deq, const BDE_OTHER_TYPE &value)
Definition bslstl_deque.h:4424
T::iterator begin(T &container)
Definition bslstl_iterator.h:1593
ALLOCATOR & lhs
Definition bslstl_string.h:3917
T::iterator end(T &container)
Definition bslstl_iterator.h:1621
Definition baljsn_encoder_testtypes.h:76
Definition bdlbb_blob.h:579
static int numTrailingUnsetBits(unsigned int value)
Definition bdlb_bitutil.h:456
static unsigned int withBitCleared(unsigned int value, int index)
Definition bdlb_bitutil.h:571
static int log2(unsigned int value)
Definition bdlb_bitutil.h:340
static unsigned int roundUpToBinaryPower(unsigned int value)
Definition bdlb_bitutil.h:540
Definition bslmf_enableif.h:530
Definition bslmf_integralconstant.h:261
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1244
static void destructiveMove(TARGET_TYPE *address, const ALLOCATOR &allocator, TARGET_TYPE *original)
Definition bslma_constructionutil.h:1296
Definition bslmf_isbitwisecopyable.h:298
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1067
Definition bsls_objectbuffer.h:277
TYPE * address()
Definition bsls_objectbuffer.h:335
TYPE & object()
Definition bsls_objectbuffer.h:352