BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdlc_flathashset.h
Go to the documentation of this file.
1/// @file bdlc_flathashset.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdlc_flathashset.h -*-C++-*-
8#ifndef INCLUDED_BDLC_FLATHASHSET
9#define INCLUDED_BDLC_FLATHASHSET
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdlc_flathashset bdlc_flathashset
15/// @brief Provide an open-addressed unordered set container.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdlc
19/// @{
20/// @addtogroup bdlc_flathashset
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdlc_flathashset-purpose"> Purpose</a>
25/// * <a href="#bdlc_flathashset-classes"> Classes </a>
26/// * <a href="#bdlc_flathashset-description"> Description </a>
27/// * <a href="#bdlc_flathashset-performance-caveats"> Performance Caveats </a>
28/// * <a href="#bdlc_flathashset-interface-differences-with-bsl-unordered_set"> Interface Differences with bsl::unordered_set </a>
29/// * <a href="#bdlc_flathashset-load-factor-and-resizing"> Load Factor and Resizing </a>
30/// * <a href="#bdlc_flathashset-requirements-on-key-hash-and-equal"> Requirements on KEY, HASH, and EQUAL </a>
31/// * <a href="#bdlc_flathashset-iterator-pointer-and-reference-invalidation"> Iterator, Pointer, and Reference Invalidation </a>
32/// * <a href="#bdlc_flathashset-exception-safety"> Exception Safety </a>
33/// * <a href="#bdlc_flathashset-move-semantics-in-c-03"> Move Semantics in C++03 </a>
34/// * <a href="#bdlc_flathashset-usage"> Usage </a>
35/// * <a href="#bdlc_flathashset-example-1-categorizing-data"> Example 1: Categorizing Data </a>
36///
37/// # Purpose {#bdlc_flathashset-purpose}
38/// Provide an open-addressed unordered set container.
39///
40/// # Classes {#bdlc_flathashset-classes}
41///
42/// - bdlc::FlatHashSet: open-addressed unordered set container
43///
44/// @see bdlc_flathashtable, bdlc_flathashmap
45///
46/// # Description {#bdlc_flathashset-description}
47/// This component defines a single class template,
48/// `bdlc::FlatHashSet`, that implements an open-addressed unordered set of
49/// items with unique values.
50///
51/// Unordered sets are useful in situations when there is no meaningful way to
52/// order key values, when the order of the values is irrelevant to the problem
53/// domain, or (even if there is a meaningful ordering) the value of ordering
54/// the results is outweighed by the higher performance provided by unordered
55/// sets (compared to ordered sets). On platforms that support relevant SIMD
56/// instructions (e.g., SSE2), `bdlc::FlatHashSet` generally exhibits better
57/// performance than `bsl::unordered_set`.
58///
59/// An instantiation of `bdlc::FlatHashSet` is an allocator-aware,
60/// value-semantic type whose salient attributes are the set of values
61/// contained, without regard to order. An instantiation may be provided with
62/// custom hash and equality functors, but those are not salient attributes. In
63/// particular, when comparing element values for equality between two different
64/// `bdlc::FlatHashSet` objects, the elements are compared using `operator==`.
65///
66/// The implemented data structure is inspired by Google's `flat_hash_map`
67/// CppCon presentations (available on YouTube). The implementation draws from
68/// Google's open source `raw_hash_set.h` file at:
69/// https://github.com/abseil/abseil-cpp/blob/master/absl/container/internal.
70///
71/// ## Performance Caveats {#bdlc_flathashset-performance-caveats}
72///
73///
74/// `bdlc::FlatHashSet` is recommended for Intel platforms *only* (i.e., Linux
75/// and Windows, and pre-ARM Macs); on platforms using other processors (i.e.,
76/// Sun and AIX), `bdlc::FlatHashSet` may have slower performance than
77/// `bsl::unordered_set`. However, note that `bdlc::FlatHashSet` will use
78/// significantly less memory than `bsl::unordered_set` on *all* platforms.
79/// Given the Intel-only performance caveat, it is recommended to benchmark
80/// before using `bdlc::FlatHashSet` -- particularly on non-Intel production
81/// environments.
82///
83/// ## Interface Differences with bsl::unordered_set {#bdlc_flathashset-interface-differences-with-bsl-unordered_set}
84///
85///
86/// A `bdlc::FlatHashSet` meets most of the requirements of an unordered
87/// associative container with forward iterators in the C++11 Standard [23.2.5].
88/// It does not have the bucket interface, and locations of elements may change
89/// when the container is modified (and therefore iterators become invalid too).
90/// Allocator use follows BDE style, and the various allocator propagation
91/// attributes are not present (e.g., the allocator trait
92/// `propagate_on_container_copy_assignment`). The maximum load factor of the
93/// container (the ratio of size to capacity) is maintained by the container
94/// itself and is not settable (the maximum load factor is implementation
95/// defined and fixed).
96///
97/// ## Load Factor and Resizing {#bdlc_flathashset-load-factor-and-resizing}
98///
99///
100/// An invariant of `bdlc::FlatHashSet` is that
101/// `0 <= load_factor() <= max_load_factor() <= 1.0`. Any operation that would
102/// result in `load_factor() > max_load_factor()` for a `bdlc::FlatHashSet`
103/// causes the capacity to increase. This resizing allocates new memory, copies
104/// or moves all elements to the new memory, and reclaims the original memory.
105/// The transfer of elements involves rehashing each element to determine its
106/// new location. As such, all iterators, pointers, and references to elements
107/// of the `bdlc::FlatHashSet` are invalidated on a resize.
108///
109/// ## Requirements on KEY, HASH, and EQUAL {#bdlc_flathashset-requirements-on-key-hash-and-equal}
110///
111///
112/// The template parameter type `KEY` must be copy or move constructible. The
113/// template parameter types `HASH` and `EQUAL` must be default and copy
114/// constructible function objects.
115///
116/// `HASH` must support a function-call operator compatible with the following
117/// statements for an object `key` of type `KEY`:
118/// @code
119/// HASH hash;
120/// bsl::size_t result = hash(key);
121/// @endcode
122///
123/// `EQUAL` must support a function-call operator compatible with the
124/// following statements for objects `key1` and `key2` of type `KEY`:
125/// @code
126/// EQUAL equal;
127/// bool result = equal(key1, key2);
128/// @endcode
129/// where the definition of the called function defines an equivalence
130/// relationship on keys that is both reflexive and transitive.
131///
132/// `HASH` and `EQUAL` function objects are further constrained: if the
133/// comparator determines that two values are equal, the hasher must produce the
134/// same hash value for each.
135///
136/// ## Iterator, Pointer, and Reference Invalidation {#bdlc_flathashset-iterator-pointer-and-reference-invalidation}
137///
138///
139/// Any change in capacity of a `bdlc::FlatHashSet` invalidates all pointers,
140/// references, and iterators. A `bdlc::FlatHashSet` manipulator that erases an
141/// element invalidates all pointers, references, and iterators to the erased
142/// element.
143///
144/// ## Exception Safety {#bdlc_flathashset-exception-safety}
145///
146///
147/// A `bdlc::FlatHashSet` is exception neutral, and all of the methods of
148/// `bdlc::FlatHashSet` provide the basic exception safety guarantee (see
149/// {@ref bsldoc_glossary |Basic Guarantee}).
150///
151/// ## Move Semantics in C++03 {#bdlc_flathashset-move-semantics-in-c-03}
152///
153///
154/// Move-only types are supported by `bdlc::FlatHashSet` on C++11, and later,
155/// platforms only (where `BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES` is defined),
156/// and are not supported on C++03 platforms. Unfortunately, in C++03, there
157/// are user-defined types where a `bslmf::MovableRef` will not safely degrade
158/// to an lvalue reference when a move constructor is not available (types
159/// providing a constructor template taking any type), so
160/// `bslmf::MovableRefUtil::move` cannot be used directly on a user-supplied
161/// template parameter type.
162///
163/// ## Usage {#bdlc_flathashset-usage}
164///
165///
166/// In this section we show intended use of this component.
167///
168/// ### Example 1: Categorizing Data {#bdlc_flathashset-example-1-categorizing-data}
169///
170///
171/// Suppose one is analyzing data on a set of customers, and each customer is
172/// categorized by several attributes: customer type, geographic area, and
173/// (internal) project code; and that each attribute takes on one of a limited
174/// set of values. This data can be handled by creating an enumeration for each
175/// of the attributes:
176/// @code
177/// typedef enum {
178/// e_REPEAT
179/// , e_DISCOUNT
180/// , e_IMPULSE
181/// , e_NEED_BASED
182/// , e_BUSINESS
183/// , e_NON_PROFIT
184/// , e_INSTITUTE
185/// // ...
186/// } CustomerCode;
187///
188/// typedef enum {
189/// e_USA_EAST
190/// , e_USA_WEST
191/// , e_CANADA
192/// , e_MEXICO
193/// , e_ENGLAND
194/// , e_SCOTLAND
195/// , e_FRANCE
196/// , e_GERMANY
197/// , e_RUSSIA
198/// // ...
199/// } LocationCode;
200///
201/// typedef enum {
202/// e_TOAST
203/// , e_GREEN
204/// , e_FAST
205/// , e_TIDY
206/// , e_PEARL
207/// , e_SMITH
208/// // ...
209/// } ProjectCode;
210/// @endcode
211/// The data set (randomly generated for this example) is provided in a
212/// statically initialized array:
213/// @code
214/// static const struct CustomerProfile {
215/// CustomerCode d_customer;
216/// LocationCode d_location;
217/// ProjectCode d_project;
218/// } customerProfiles[] = {
219/// { e_IMPULSE , e_CANADA , e_SMITH },
220/// { e_NON_PROFIT, e_USA_EAST, e_GREEN },
221/// { e_INSTITUTE , e_USA_EAST, e_TOAST },
222/// { e_NON_PROFIT, e_CANADA , e_PEARL },
223/// { e_NEED_BASED, e_CANADA , e_FAST },
224/// { e_BUSINESS , e_ENGLAND , e_PEARL },
225/// { e_REPEAT , e_SCOTLAND, e_TIDY },
226/// { e_INSTITUTE , e_MEXICO , e_PEARL },
227/// { e_DISCOUNT , e_USA_EAST, e_GREEN },
228/// { e_BUSINESS , e_USA_EAST, e_GREEN },
229/// { e_IMPULSE , e_MEXICO , e_TOAST },
230/// { e_DISCOUNT , e_GERMANY , e_FAST },
231/// { e_INSTITUTE , e_FRANCE , e_FAST },
232/// { e_NON_PROFIT, e_ENGLAND , e_PEARL },
233/// { e_BUSINESS , e_ENGLAND , e_TIDY },
234/// { e_BUSINESS , e_CANADA , e_GREEN },
235/// { e_INSTITUTE , e_FRANCE , e_FAST },
236/// { e_IMPULSE , e_RUSSIA , e_TOAST },
237/// { e_REPEAT , e_USA_WEST, e_TOAST },
238/// { e_IMPULSE , e_CANADA , e_TIDY },
239/// { e_NON_PROFIT, e_GERMANY , e_GREEN },
240/// { e_INSTITUTE , e_USA_EAST, e_TOAST },
241/// { e_INSTITUTE , e_FRANCE , e_FAST },
242/// { e_IMPULSE , e_SCOTLAND, e_SMITH },
243/// { e_INSTITUTE , e_USA_EAST, e_PEARL },
244/// { e_INSTITUTE , e_USA_EAST, e_TOAST },
245/// { e_NON_PROFIT, e_ENGLAND , e_PEARL },
246/// { e_IMPULSE , e_GERMANY , e_FAST },
247/// { e_REPEAT , e_GERMANY , e_FAST },
248/// { e_REPEAT , e_MEXICO , e_PEARL },
249/// { e_IMPULSE , e_GERMANY , e_TIDY },
250/// { e_IMPULSE , e_MEXICO , e_TOAST },
251/// { e_NON_PROFIT, e_SCOTLAND, e_SMITH },
252/// { e_NEED_BASED, e_MEXICO , e_TOAST },
253/// { e_NON_PROFIT, e_FRANCE , e_SMITH },
254/// { e_INSTITUTE , e_MEXICO , e_TIDY },
255/// { e_NON_PROFIT, e_FRANCE , e_TIDY },
256/// { e_IMPULSE , e_FRANCE , e_FAST },
257/// { e_DISCOUNT , e_RUSSIA , e_TIDY },
258/// { e_IMPULSE , e_USA_EAST, e_TIDY },
259/// { e_IMPULSE , e_USA_WEST, e_FAST },
260/// { e_NON_PROFIT, e_FRANCE , e_TIDY },
261/// { e_BUSINESS , e_ENGLAND , e_GREEN },
262/// { e_REPEAT , e_FRANCE , e_TOAST },
263/// { e_REPEAT , e_RUSSIA , e_SMITH },
264/// { e_REPEAT , e_RUSSIA , e_GREEN },
265/// { e_IMPULSE , e_CANADA , e_FAST },
266/// { e_NON_PROFIT, e_USA_EAST, e_FAST },
267/// { e_NEED_BASED, e_USA_WEST, e_TOAST },
268/// { e_NON_PROFIT, e_GERMANY , e_TIDY },
269/// { e_NON_PROFIT, e_ENGLAND , e_GREEN },
270/// { e_REPEAT , e_GERMANY , e_PEARL },
271/// { e_NEED_BASED, e_USA_EAST, e_PEARL },
272/// { e_NON_PROFIT, e_RUSSIA , e_PEARL },
273/// { e_NEED_BASED, e_ENGLAND , e_SMITH },
274/// { e_INSTITUTE , e_CANADA , e_SMITH },
275/// { e_NEED_BASED, e_ENGLAND , e_TOAST },
276/// { e_NON_PROFIT, e_MEXICO , e_TIDY },
277/// { e_BUSINESS , e_GERMANY , e_FAST },
278/// { e_NEED_BASED, e_SCOTLAND, e_PEARL },
279/// { e_NON_PROFIT, e_USA_WEST, e_TIDY },
280/// { e_NON_PROFIT, e_USA_WEST, e_TOAST },
281/// { e_IMPULSE , e_FRANCE , e_PEARL },
282/// { e_IMPULSE , e_ENGLAND , e_FAST },
283/// { e_IMPULSE , e_USA_WEST, e_GREEN },
284/// { e_DISCOUNT , e_MEXICO , e_SMITH },
285/// { e_INSTITUTE , e_GERMANY , e_TOAST },
286/// { e_NEED_BASED, e_CANADA , e_PEARL },
287/// { e_NON_PROFIT, e_USA_WEST, e_FAST },
288/// { e_DISCOUNT , e_RUSSIA , e_SMITH },
289/// { e_INSTITUTE , e_USA_WEST, e_GREEN },
290/// { e_INSTITUTE , e_RUSSIA , e_TOAST },
291/// { e_INSTITUTE , e_FRANCE , e_SMITH },
292/// { e_INSTITUTE , e_SCOTLAND, e_SMITH },
293/// { e_NON_PROFIT, e_ENGLAND , e_PEARL },
294/// { e_NON_PROFIT, e_CANADA , e_SMITH },
295/// { e_NON_PROFIT, e_USA_EAST, e_TOAST },
296/// { e_REPEAT , e_FRANCE , e_TOAST },
297/// { e_NEED_BASED, e_FRANCE , e_FAST },
298/// { e_DISCOUNT , e_MEXICO , e_TOAST },
299/// { e_DISCOUNT , e_FRANCE , e_GREEN },
300/// { e_IMPULSE , e_USA_EAST, e_FAST },
301/// { e_REPEAT , e_USA_EAST, e_GREEN },
302/// { e_NON_PROFIT, e_GERMANY , e_GREEN },
303/// { e_INSTITUTE , e_CANADA , e_SMITH },
304/// { e_NEED_BASED, e_SCOTLAND, e_TOAST },
305/// { e_NEED_BASED, e_GERMANY , e_FAST },
306/// { e_NON_PROFIT, e_RUSSIA , e_TOAST },
307/// { e_BUSINESS , e_ENGLAND , e_PEARL },
308/// { e_NEED_BASED, e_USA_EAST, e_TOAST },
309/// { e_INSTITUTE , e_USA_EAST, e_SMITH },
310/// { e_DISCOUNT , e_USA_EAST, e_PEARL },
311/// { e_REPEAT , e_SCOTLAND, e_FAST },
312/// { e_IMPULSE , e_GERMANY , e_TIDY },
313/// { e_DISCOUNT , e_CANADA , e_TIDY },
314/// { e_IMPULSE , e_USA_EAST, e_TIDY },
315/// { e_IMPULSE , e_GERMANY , e_TIDY },
316/// { e_NON_PROFIT, e_ENGLAND , e_FAST },
317/// { e_NON_PROFIT, e_USA_WEST, e_TIDY },
318/// { e_REPEAT , e_MEXICO , e_TOAST },
319/// };
320/// const bsl::size_t numCustomerProfiles = sizeof customerProfiles
321/// / sizeof *customerProfiles;
322/// @endcode
323/// Suppose, as the first step in our analysis, we wish to determine the number
324/// of unique combinations of customer attributes that exist in our data set.
325/// We can do that by inserting each data item into a flat hash set: the first
326/// insert of a combination will succeed, the others will fail, but at the end
327/// of the process, the set will contain one entry for every unique combination
328/// in our data.
329///
330/// First, as there are no standard methods for hashing or comparing our
331/// user-defined types, we define `CustomerProfileHash` and
332/// `CustomerProfileEqual` classes, each a stateless functor. Note that there
333/// is no meaningful ordering of the attribute values, they are merely arbitrary
334/// code numbers; nothing is lost by using an unordered set instead of an
335/// ordered set:
336/// @code
337/// class CustomerProfileHash {
338/// public:
339/// // CREATORS
340/// //! CustomerProfileHash() = default;
341/// // Create a 'CustomerProfileHash' object.
342///
343/// //! CustomerProfileHash(const CustomerProfileHash& original) = default;
344/// // Create a 'CustomerProfileHash' object. Note that as
345/// // 'CustomerProfileHash' is an empty (stateless) type, this
346/// // operation has no observable effect.
347///
348/// //! ~CustomerProfileHash() = default;
349/// // Destroy this object.
350///
351/// // ACCESSORS
352/// bsl::size_t operator()(const CustomerProfile& x) const;
353/// // Return a hash value for the specified 'x'.
354/// };
355/// @endcode
356/// The hash function combines the several enumerated values from the class
357/// (each a small `int` value) into a single, unique `int` value, and then
358/// applies the default hash function for `int`.
359/// @code
360/// // ACCESSORS
361/// bsl::size_t CustomerProfileHash::operator()(const CustomerProfile& x) const
362/// {
363/// return bsl::hash<int>()( x.d_location * 100 * 100
364/// + x.d_customer * 100
365/// + x.d_project);
366/// }
367///
368/// class CustomerProfileEqual {
369/// public:
370/// // CREATORS
371/// //! CustomerProfileEqual() = default;
372/// // Create a 'CustomerProfileEqual' object.
373///
374/// //! CustomerProfileEqual(const CustomerProfileEqual& original)
375/// //! = default;
376/// // Create a 'CustomerProfileEqual' object. Note that as
377/// // 'CustomerProfileEqual' is an empty (stateless) type, this
378/// // operation has no observable effect.
379///
380/// //! ~CustomerProfileEqual() = default;
381/// // Destroy this object.
382///
383/// // ACCESSORS
384/// bool operator()(const CustomerProfile& lhs,
385/// const CustomerProfile& rhs) const;
386/// // Return 'true' if the specified 'lhs' has the same value as the
387/// // specified 'rhs', and 'false' otherwise.
388/// };
389///
390/// // ACCESSORS
391/// bool CustomerProfileEqual::operator()(const CustomerProfile& lhs,
392/// const CustomerProfile& rhs) const
393/// {
394/// return lhs.d_location == rhs.d_location
395/// && lhs.d_customer == rhs.d_customer
396/// && lhs.d_project == rhs.d_project;
397/// }
398/// @endcode
399/// Notice that many of the required methods of the hash and comparator types
400/// are compiler generated. (The declarations of those methods are commented
401/// out and suffixed by an `= default` comment.)
402///
403/// Then, we define the type of the flat hash set:
404/// @code
405/// typedef bdlc::FlatHashSet<CustomerProfile,
406/// CustomerProfileHash,
407/// CustomerProfileEqual> ProfileCategories;
408/// @endcode
409/// Next, we create a flat hash set and insert each item of `customerProfiles`:
410/// @code
411/// bslma::TestAllocator oa("object", veryVeryVeryVerbose);
412///
413/// ProfileCategories profileCategories(&oa);
414///
415/// for (bsl::size_t idx = 0; idx < numCustomerProfiles; ++idx) {
416/// profileCategories.insert(customerProfiles[idx]);
417/// }
418///
419/// assert(numCustomerProfiles >= profileCategories.size());
420/// @endcode
421/// Notice that we ignore the status returned by the `insert` method. We fully
422/// expect some operations to fail.
423///
424/// Finally, the size of `profileCategories` matches the number of unique
425/// customer profiles in this data set:
426/// @code
427/// if (verbose) {
428/// bsl::cout << numCustomerProfiles << ' ' << profileCategories.size()
429/// << bsl::endl;
430/// }
431/// @endcode
432/// Standard output shows:
433/// @code
434/// 100 84
435/// @endcode
436/// @}
437/** @} */
438/** @} */
439
440/** @addtogroup bdl
441 * @{
442 */
443/** @addtogroup bdlc
444 * @{
445 */
446/** @addtogroup bdlc_flathashset
447 * @{
448 */
449
450#include <bdlscm_version.h>
451
452#include <bdlc_flathashtable.h>
453
455#include <bslalg_swaputil.h>
456
458
459#include <bslim_printer.h>
460
461#include <bslma_allocator.h>
464
465#include <bslmf_enableif.h>
466#include <bslmf_isconvertible.h>
467#include <bslmf_movableref.h>
468#include <bslmf_util.h> // 'forward(V)'
469
470#include <bsls_assert.h>
472#include <bsls_platform.h>
473#include <bsls_util.h> // 'forward<T>(V)'
474
475#include <bslstl_equalto.h>
476#include <bslstl_hash.h>
477
478#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
479#include <bsl_initializer_list.h>
480#endif
481#include <bsl_cstddef.h>
482#include <bsl_ostream.h>
483#include <bsl_utility.h>
484
485#if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
486// Include version that can be compiled with C++03
487// Generated on Thu Jan 25 11:18:32 2024
488// Command line: sim_cpp11_features.pl bdlc_flathashset.h
489# define COMPILING_BDLC_FLATHASHSET_H
490# include <bdlc_flathashset_cpp03.h>
491# undef COMPILING_BDLC_FLATHASHSET_H
492#else
493
494
495namespace bdlc {
496
497// FORWARD DECLARATIONS
498template <class KEY,
500 class EQUAL = bsl::equal_to<KEY> >
501class FlatHashSet;
502
503template <class KEY, class HASH, class EQUAL>
504bool operator==(const FlatHashSet<KEY, HASH, EQUAL> &a,
506
507template <class KEY, class HASH, class EQUAL>
508bool operator!=(const FlatHashSet<KEY, HASH, EQUAL> &a,
510
511template <class KEY, class HASH, class EQUAL>
513
514 // ============================
515 // struct FlatHashSet_EntryUtil
516 // ============================
517
518/// This templated utility provides methods to construct an `ENTRY` and a
519/// method to extract the key from an `ENTRY` (which is, identically, the
520/// `ENTRY`).
521template <class ENTRY>
523{
524 // CLASS METHODS
525#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
526 /// Load into the specified `entry` the `ENTRY` value constructed from
527 /// specified `args`, using the specified `allocator` to supply memory.
528 /// `allocator` is ignored if the (template parameter) type `ENTRY` is
529 /// not allocator aware.
530 template <class... ARGS>
531 static void construct(
532 ENTRY *entry,
533 bslma::Allocator *allocator,
534 ARGS&&... args);
535#endif
536
537 /// Load into the specified `entry` the `ENTRY` value comprised of the
538 /// specified `key`, using the specified `allocator` to supply memory.
539 /// `allocator` is ignored if the (template parameter) type `ENTRY` is
540 /// not allocator aware.
541 template <class KEY_TYPE>
542 static void constructFromKey(
543 ENTRY *entry,
544 bslma::Allocator *allocator,
546
547 /// Return the specified `entry`.
548 static const ENTRY& key(const ENTRY& entry);
549};
550
551 // =================
552 // class FlatHashSet
553 // =================
554
555/// This class template implements a value-semantic container type holding
556/// an unordered set of unique values of (template parameter) type `KEY`.
557/// The (template parameter) type `HASH` is a functor providing the hash
558/// value for `KEY`. The (template parameter) type `EQUAL` is a functor
559/// providing the equality function for two `KEY` values. See {Requirements
560/// on `KEY`, `HASH`, and `EQUAL`} for more information.
561///
562/// See @ref bdlc_flathashset
563template <class KEY, class HASH, class EQUAL>
565
566 private:
567 // PRIVATE TYPES
568
569 /// This is the underlying implementation class.
570 typedef FlatHashTable<KEY,
571 KEY,
573 HASH,
574 EQUAL> ImplType;
575
576 // FRIENDS
577 friend bool operator==<>(const FlatHashSet&, const FlatHashSet&);
578 friend bool operator!=<>(const FlatHashSet&, const FlatHashSet&);
579
580 // The following verbose declaration is required by the xlC 12.1 compiler.
581 template <class K, class H, class E>
583
584 public:
585 // PUBLIC TYPES
586 typedef KEY key_type;
587 typedef KEY value_type;
588 typedef bsl::size_t size_type;
589 typedef bsl::ptrdiff_t difference_type;
590 typedef EQUAL key_compare;
591 typedef EQUAL value_compare;
592 typedef HASH hasher;
596 typedef const value_type* const_pointer;
599
600 private:
601 // DATA
602 ImplType d_impl; // underlying flat hash table used by this flat hash set
603
604 public:
605 // CREATORS
606
607 FlatHashSet();
608 explicit FlatHashSet(bslma::Allocator *basicAllocator);
609 explicit FlatHashSet(bsl::size_t capacity);
610 FlatHashSet(bsl::size_t capacity, bslma::Allocator *basicAllocator);
611 FlatHashSet(bsl::size_t capacity,
612 const HASH& hash,
613 bslma::Allocator *basicAllocator = 0);
614 /// Create an empty `FlatHashSet` object. Optionally specify a
615 /// `capacity` indicating the minimum initial size of the underlying
616 /// array of entries of this container. If `capacity` is not supplied
617 /// or is 0, no memory is allocated. Optionally specify a `hash`
618 /// functor used to generate the hash values associated with the
619 /// elements in this container. If `hash` is not supplied, a
620 /// default-constructed object of the (template parameter) type `HASH`
621 /// is used. Optionally specify an equality functor `equal` used to
622 /// determine whether two elements are equivalent. If `equal` is not
623 /// supplied, a default-constructed object of the (template parameter)
624 /// type `EQUAL` is used. Optionally specify a `basicAllocator` used to
625 /// supply memory. If `basicAllocator` is not supplied or is 0, the
626 /// currently installed default allocator is used.
627 FlatHashSet(bsl::size_t capacity,
628 const HASH& hash,
629 const EQUAL& equal,
630 bslma::Allocator *basicAllocator = 0);
631
632 /// Create a `FlatHashSet` object initialized by insertion of the values
633 /// from the input iterator range specified by `first` through `last`
634 /// (including `first`, excluding `last`). Optionally specify a
635 /// `capacity` indicating the minimum initial size of the underlying
636 /// array of entries of this container. If `capacity` is not supplied
637 /// or is 0, no memory is allocated. Optionally specify a `hash`
638 /// functor used to generate hash values associated with the elements in
639 /// this container. If `hash` is not supplied, a default-constructed
640 /// object of the (template parameter) type `HASH` is used. Optionally
641 /// specify an equality functor `equal` used to verify that two elements
642 /// are equivalent. If `equal` is not supplied, a default-constructed
643 /// object of the (template parameter) type `EQUAL` is used. Optionally
644 /// specify a `basicAllocator` used to supply memory. If
645 /// `basicAllocator` is not supplied or is 0, the currently installed
646 /// default allocator is used. The behavior is undefined unless `first`
647 /// and `last` refer to a sequence of valid values where `first` is at a
648 /// position at or before `last`. Note that if a member of the input
649 /// sequence is equivalent to an earlier member, the later member will
650 /// not be inserted.
651 template <class INPUT_ITERATOR>
652 FlatHashSet(INPUT_ITERATOR first,
653 INPUT_ITERATOR last,
654 bslma::Allocator *basicAllocator = 0);
655 template <class INPUT_ITERATOR>
656 FlatHashSet(INPUT_ITERATOR first,
657 INPUT_ITERATOR last,
658 bsl::size_t capacity,
659 bslma::Allocator *basicAllocator = 0);
660 template <class INPUT_ITERATOR>
661 FlatHashSet(INPUT_ITERATOR first,
662 INPUT_ITERATOR last,
663 bsl::size_t capacity,
664 const HASH& hash,
665 bslma::Allocator *basicAllocator = 0);
666 template <class INPUT_ITERATOR>
667 FlatHashSet(INPUT_ITERATOR first,
668 INPUT_ITERATOR last,
669 bsl::size_t capacity,
670 const HASH& hash,
671 const EQUAL& equal,
672 bslma::Allocator *basicAllocator = 0);
673
674#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
675 FlatHashSet(bsl::initializer_list<KEY> values,
676 bslma::Allocator *basicAllocator = 0);
677 FlatHashSet(bsl::initializer_list<KEY> values,
678 bsl::size_t capacity,
679 bslma::Allocator *basicAllocator = 0);
680 FlatHashSet(bsl::initializer_list<KEY> values,
681 bsl::size_t capacity,
682 const HASH& hash,
683 bslma::Allocator *basicAllocator = 0);
684 /// Create a `FlatHashSet` object initialized by insertion of the
685 /// specified `values`. Optionally specify a `capacity` indicating the
686 /// minimum initial size of the underlying array of entries of this
687 /// container. If `capacity` is not supplied or is 0, no memory is
688 /// allocated. Optionally specify a `hash` functor used to generate
689 /// hash values associated with the elements in this container. If
690 /// `hash` is not supplied, a default-constructed object of the
691 /// (template parameter) type `HASH` is used. Optionally specify an
692 /// equality functor `equal` used to verify that two elements are
693 /// equivalent. If `equal` is not supplied, a default-constructed
694 /// object of the (template parameter) type `EQUAL` is used. Optionally
695 /// specify a `basicAllocator` used to supply memory. If
696 /// `basicAllocator` is not supplied or is 0, the currently installed
697 /// default allocator is used. Note that if a member of `values` has a
698 /// key equivalent to an earlier member, the later member will not be
699 /// inserted.
700 FlatHashSet(bsl::initializer_list<KEY> values,
701 bsl::size_t capacity,
702 const HASH& hash,
703 const EQUAL& equal,
704 bslma::Allocator *basicAllocator = 0);
705#endif
706
707 /// Create a `FlatHashSet` object having the same value, hasher, and
708 /// equality comparator as the specified `original` object. Optionally
709 /// specify a `basicAllocator` used to supply memory. If
710 /// `basicAllocator` is not specified or is 0, the currently installed
711 /// default allocator is used.
712 FlatHashSet(const FlatHashSet& original,
713 bslma::Allocator *basicAllocator = 0);
714
715 /// Create a `FlatHashSet` object having the same value, hasher,
716 /// equality comparator, and allocator as the specified `original`
717 /// object. The contents of `original` are moved (in constant time) to
718 /// this object, `original` is left in a (valid) unspecified state, and
719 /// no exceptions will be thrown.
721
722 /// Create a `FlatHashSet` object having the same value, hasher, and
723 /// equality comparator as the specified `original` object, using the
724 /// specified `basicAllocator` to supply memory. If `basicAllocator` is
725 /// 0, the currently installed default allocator is used. The allocator
726 /// of `original` remains unchanged. If `original` and the newly
727 /// created object have the same allocator then the contents of
728 /// `original` are moved (in constant time) to this object, `original`
729 /// is left in a (valid) unspecified state, and no exceptions will be
730 /// thrown; otherwise `original` is unchanged (and an exception may be
731 /// thrown).
733 bslma::Allocator *basicAllocator);
734
735 /// Destroy this object and each of its elements.
736 ~FlatHashSet();
737
738 // MANIPULATORS
739
740 /// Assign to this object the value, hasher, and equality functor of the
741 /// specified `rhs` object, and return a reference providing modifiable
742 /// access to this object.
743 FlatHashSet& operator=(const FlatHashSet& rhs);
744
745 /// Assign to this object the value, hasher, and equality comparator of
746 /// the specified `rhs` object, and return a reference providing
747 /// modifiable access to this object. If this object and `rhs` use the
748 /// same allocator the contents of `rhs` are moved (in constant time) to
749 /// this object. `rhs` is left in a (valid) unspecified state.
751
752#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
753 /// Assign to this object the value resulting from first clearing this
754 /// set and then inserting each object in the specified `values`
755 /// initializer list, ignoring those objects having a value equivalent
756 /// to that which appears earlier in the list; return a reference
757 /// providing modifiable access to this object. This method requires
758 /// that the (template parameter) type `KEY` be `copy-insertable` into
759 /// this set (see {Requirements on `KEY`, `HASH`, and `EQUAL`}).
760 FlatHashSet& operator=(bsl::initializer_list<KEY> values);
761#endif
762
763 /// Remove all elements from this set. Note that this set will be empty
764 /// after calling this method, but allocated memory may be retained for
765 /// future use. See the `capacity` method.
766 void clear();
767
768#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
769 /// Insert into this set a newly created `value_type` object,
770 /// constructed by forwarding `get_allocator()` (if required) and the
771 /// specified (variable number of) `args` to the corresponding
772 /// constructor of `value_type`, if a key equivalent to such a value
773 /// does not already exist in this set; otherwise, this method has no
774 /// effect (other than possibly creating a temporary `value_type`
775 /// object). Return a pair whose `first` member is an iterator
776 /// referring to the (possibly newly created and inserted) object in
777 /// this set whose value is equivalent to that of an object constructed
778 /// from `arguments`, and whose `second` member is `true` if a new value
779 /// was inserted, and `false` if an equivalent key was already present.
780 template <class... ARGS>
782
783 /// Insert into this set a newly created `value_type` object,
784 /// constructed by forwarding `get_allocator()` (if required) and the
785 /// specified (variable number of) `args` to the corresponding
786 /// constructor of `value_type`, if a key equivalent to such a value
787 /// does not already exists in this set; otherwise, this method has no
788 /// effect (other than possibly creating a temporary `value_type`
789 /// object). Return an iterator referring to the (possibly newly
790 /// created and inserted) object in this set whose value is equivalent
791 /// to that of an object constructed from `arguments`. The average and
792 /// worst case complexity of this operation is not affected by the
793 /// specified `hint`. Note that `hint` is ignored (other than possibly
794 /// asserting its validity in some build modes).
795 template <class... ARGS>
796 iterator emplace_hint(const_iterator hint, ARGS&&... args);
797
798#endif
799
800 /// Remove from this set the element whose key is equal to the specified
801 /// `key`, if it exists, and return 1; otherwise (there is no element
802 /// having `key` in this set), return 0 with no other effect. This
803 /// method invalidates all iterators and references to the removed
804 /// element.
805 bsl::size_t erase(const KEY& key);
806
807 /// Remove from this set the element at the specified `position`, and
808 /// return a `const_iterator` referring to the element immediately
809 /// following the removed element, or to the past-the-end position if
810 /// the removed element was the last element in the sequence of elements
811 /// maintained by this set. This method invalidates all iterators and
812 /// references to the removed element. The behavior is undefined unless
813 /// `position` refers to an element in this set.
815
816 /// Remove from this set the elements starting at the specified `first`
817 /// position up to, but not including, the specified `last` position,
818 /// and return `last`. This method invalidates all iterators and
819 /// references to the removed elements. The behavior is undefined
820 /// unless `first` and `last` are valid iterators on this set, and the
821 /// `first` position is at or before the `last` position in the
822 /// iteration sequence provided by this container.
824
825#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
826 template <class KEY_TYPE>
828 BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) value)
829#else
830 /// Insert the specified `value` into this set if the `value` does not
831 /// already exist in this set; otherwise, this method has no effect.
832 /// Return a `pair` whose `first` member is a `const_iterator` referring
833 /// to the (possibly newly inserted) element in this set whose value is
834 /// equivalent to that of the element to be inserted, and whose `second`
835 /// member is `true` if a new element was inserted, and `false` if an
836 /// equivalent value was already present.
837 template <class KEY_TYPE>
841#endif
842 {
843 // Note that some compilers require functions declared with 'enable_if'
844 // to be defined inline.
845
846 return d_impl.insert(BSLS_COMPILERFEATURES_FORWARD(KEY_TYPE, value));
847 }
848
849#if defined(BSLS_PLATFORM_CMP_SUN) && BSLS_PLATFORM_CMP_VERSION < 0x5130
850 template <class KEY_TYPE>
852 BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) value)
853#else
854 /// Insert the specified `value` into this set if the `value` does not
855 /// already exist in this set; otherwise, this method has no effect.
856 /// Return a `const_iterator` referring to the (possibly newly inserted)
857 /// element in this set whose value is equivalent to that of the
858 /// element to be inserted. The supplied `const_iterator` is ignored.
859 template <class KEY_TYPE>
861 const_iterator>::type
863 BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) value)
864#endif
865 {
866 // Note that some compilers require functions declared with 'enable_if'
867 // to be defined inline.
868
869 return d_impl.insert(BSLS_COMPILERFEATURES_FORWARD(KEY_TYPE,
870 value)).first;
871 }
872
873 /// Insert into this set the value of each element in the input iterator
874 /// range specified by `first` through `last` (including `first`,
875 /// excluding `last`). The behavior is undefined unless `first` and
876 /// `last` refer to a sequence of valid values where `first` is at a
877 /// position at or before `last`. Note that if a member of the input
878 /// sequence is equivalent to an earlier member, the later member will
879 /// not be inserted.
880 template <class INPUT_ITERATOR>
881 void insert(INPUT_ITERATOR first, INPUT_ITERATOR last);
882
883#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
884 /// Insert into this set an element having the value of each object in
885 /// the specified `values` initializer list if an equivalent value is
886 /// not already contained in this set. This method requires that the
887 /// (template parameter) type `KEY` be copy-insertable (see
888 /// {Requirements on `KEY`, `HASH`, and `EQUAL`}).
889 void insert(bsl::initializer_list<KEY> values);
890#endif
891
892 /// Change the capacity of this set to at least the specified
893 /// `minimumCapacity`, and redistribute all the contained elements into
894 /// a new sequence of entries according to their hash values. If
895 /// `0 == minimumCapacity` and `0 == size()`, the set is returned to the
896 /// default constructed state. After this call, `load_factor()` will be
897 /// less than or equal to `max_load_factor()` and all iterators,
898 /// pointers, and references to elements of this set are invalidated.
899 void rehash(bsl::size_t minimumCapacity);
900
901 /// Change the capacity of this set to at least a capacity that can
902 /// accommodate the specified `numEntries` (accounting for the load
903 /// factor invariant), and redistribute all the contained elements into
904 /// a new sequence of entries according to their hash values. If
905 /// `0 == numEntries` and `0 == size()`, the set is returned to the
906 /// default constructed state. After this call, `load_factor()` will be
907 /// less than or equal to `max_load_factor()` and all iterators,
908 /// pointers, and references to elements of this set are invalidated.
909 /// Note that this method is effectively equivalent to:
910 /// @code
911 /// rehash(bsl::ceil(numEntries / max_load_factor()))
912 /// @endcode
913 void reserve(bsl::size_t numEntries);
914
915 /// Remove all elements from this set and release all memory from this
916 /// set, returning the set to the default constructed state.
917 void reset();
918
919 // Aspects
920
921 /// Exchange the value of this object as well as its hasher and equality
922 /// functors with those of the specified `other` object. The behavior
923 /// is undefined unless this object was created with the same allocator
924 /// as `other`.
925 void swap(FlatHashSet& other);
926
927 // ACCESSORS
928
929 /// Return the number of elements this set could hold if the load factor
930 /// were 1.
931 bsl::size_t capacity() const;
932
933 /// Return `true` if this set contains an element having the specified
934 /// `key`, and `false` otherwise.
935 bool contains(const KEY& key) const;
936
937 /// Return the number of elements in this set having the specified
938 /// `key`. Note that since a flat hash set maintains unique keys, the
939 /// returned value will be either 0 or 1.
940 bsl::size_t count(const KEY& key) const;
941
942 /// Return `true` if this set contains no elements, and `false`
943 /// otherwise.
944 bool empty() const;
945
946 /// Return a pair of `const_iterator`s defining the sequence of elements
947 /// in this set having the specified `key`, where the first iterator is
948 /// positioned at the start of the sequence and the second iterator is
949 /// positioned one past the end of the sequence. If this set contains
950 /// no `KEY` elements equivalent to `key`, then the two returned
951 /// iterators will have the same value. Note that since a set maintains
952 /// unique keys, the range will contain at most one element.
954 const KEY& key) const;
955
956 /// Return a `const_iterator` referring to the element in this set
957 /// having the specified `key`, or `end()` if no such entry exists in
958 /// this set.
959 const_iterator find(const KEY& key) const;
960
961 /// Return (a copy of) the unary hash functor used by this set to
962 /// generate a hash value (of type `bsl::size_t`) for a `KEY` object.
963 HASH hash_function() const;
964
965 /// Return (a copy of) the binary key-equality functor that returns
966 /// `true` if the value of two `KEY` objects are equivalent, and `false`
967 /// otherwise.
968 EQUAL key_eq() const;
969
970 /// Return the current ratio between the number of elements in this
971 /// container and its capacity.
972 float load_factor() const;
973
974 /// Return the maximum load factor allowed for this set. Note that if
975 /// an insert operation would cause the load factor to exceed
976 /// `max_load_factor()`, that same insert operation will increase the
977 /// capacity and rehash the entries of the container (see {Load Factor
978 /// and Resizing}). Also note that the value returned by
979 /// `max_load_factor` is implementation defined and cannot be changed by
980 /// the user.
981 float max_load_factor() const;
982
983 /// Return the number of elements in this set.
984 bsl::size_t size() const;
985
986 // Iterators
987
988 /// Return a `const_iterator` to the first element in the sequence of
989 /// elements maintained by this set, or the `end` iterator if this set
990 /// is empty.
991 const_iterator begin() const;
992
993 /// Return a `const_iterator` to the first element in the sequence of
994 /// elements maintained by this set, or the `end` iterator if this set
995 /// is empty.
996 const_iterator cbegin() const;
997
998 /// Return a `const_iterator` to the past-the-end element in the
999 /// sequence of `KEY` elements maintained by this set.
1000 const_iterator cend() const;
1001
1002 /// Return a `const_iterator` to the past-the-end element in the
1003 /// sequence of `KEY` elements maintained by this set.
1004 const_iterator end() const;
1005
1006 // Aspects
1007
1008 /// Return the allocator used by this flat hash set to supply memory.
1009 bslma::Allocator *allocator() const;
1010
1011 /// Format this object to the specified output `stream` at the (absolute
1012 /// value of) the optionally specified indentation `level`, and return a
1013 /// reference to the modifiable `stream`. If `level` is specified,
1014 /// optionally specify `spacesPerLevel`, the number of spaces per
1015 /// indentation level for this and all of its nested objects. If
1016 /// `level` is negative, suppress indentation of the first line. If
1017 /// `spacesPerLevel` is negative, format the entire output on one line,
1018 /// suppressing all but the initial indentation (as governed by
1019 /// `level`). If `stream` is not valid on entry, this operation has no
1020 /// effect.
1021 bsl::ostream& print(bsl::ostream& stream,
1022 int level = 0,
1023 int spacesPerLevel = 4) const;
1024};
1025
1026// FREE OPERATORS
1027
1028/// Return `true` if the specified `lhs` and `rhs` objects have the same
1029/// value, and `false` otherwise. Two `FlatHashSet` objects have the same
1030/// value if their sizes are the same and each element contained in one is
1031/// equal to an element of the other. The hash and equality functors are
1032/// not involved in the comparison.
1033template <class KEY, class HASH, class EQUAL>
1034bool operator==(const FlatHashSet<KEY, HASH, EQUAL> &lhs,
1035 const FlatHashSet<KEY, HASH, EQUAL> &rhs);
1036
1037/// Return `true` if the specified `lhs` and `rhs` objects do not have the
1038/// same value, and `false` otherwise. Two `FlatHashSet` objects do not
1039/// have the same value if their sizes are different or one contains an
1040/// element equal to no element of the other. The hash and equality
1041/// functors are not involved in the comparison.
1042template <class KEY, class HASH, class EQUAL>
1043bool operator!=(const FlatHashSet<KEY, HASH, EQUAL> &lhs,
1044 const FlatHashSet<KEY, HASH, EQUAL> &rhs);
1045
1046/// Write the value of the specified `set` to the specified output `stream`
1047/// in a single-line format, and return a reference providing modifiable
1048/// access to `stream`. If `stream` is not valid on entry, this operation
1049/// has no effect. Note that this human-readable format is not fully
1050/// specified and can change without notice.
1051template <class KEY, class HASH, class EQUAL>
1052bsl::ostream& operator<<(bsl::ostream& stream,
1054
1055// FREE FUNCTIONS
1056
1057/// Exchange the value, the hasher, and the key-equality functor of the
1058/// specified `a` and `b` objects. This function provides the no-throw
1059/// exception-safety guarantee if the two objects were created with the same
1060/// allocator and the basic guarantee otherwise.
1061template <class KEY, class HASH, class EQUAL>
1063
1064// ============================================================================
1065// TEMPLATE AND INLINE FUNCTION DEFINITIONS
1066// ============================================================================
1067
1068 // ----------------------------
1069 // struct FlatHashSet_EntryUtil
1070 // ----------------------------
1071
1072// CLASS METHODS
1073#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1074template <class ENTRY>
1075template <class... ARGS>
1076inline
1078 ENTRY *entry,
1079 bslma::Allocator *allocator,
1080 ARGS&&... args)
1081{
1082 BSLS_ASSERT_SAFE(entry);
1084 entry,
1085 allocator,
1086 BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
1087}
1088#endif
1089
1090template <class ENTRY>
1091template <class KEY>
1092inline
1094 ENTRY *entry,
1095 bslma::Allocator *allocator,
1097{
1098 BSLS_ASSERT_SAFE(entry);
1099
1101 entry,
1102 allocator,
1104}
1105
1106template <class ENTRY>
1107inline
1108const ENTRY& FlatHashSet_EntryUtil<ENTRY>::key(const ENTRY& entry)
1109{
1110 return entry;
1111}
1112
1113 // -----------------
1114 // class FlatHashSet
1115 // -----------------
1116
1117// CREATORS
1118template <class KEY, class HASH, class EQUAL>
1119inline
1121: d_impl(0, HASH(), EQUAL())
1122{
1123}
1124
1125template <class KEY, class HASH, class EQUAL>
1126inline
1128: d_impl(0, HASH(), EQUAL(), basicAllocator)
1129{
1130}
1131
1132template <class KEY, class HASH, class EQUAL>
1133inline
1135: d_impl(capacity, HASH(), EQUAL())
1136{
1137}
1138
1139template <class KEY, class HASH, class EQUAL>
1140inline
1142 bslma::Allocator *basicAllocator)
1143: d_impl(capacity, HASH(), EQUAL(), basicAllocator)
1144{
1145}
1146
1147template <class KEY, class HASH, class EQUAL>
1148inline
1150 const HASH& hash,
1151 bslma::Allocator *basicAllocator)
1152: d_impl(capacity, hash, EQUAL(), basicAllocator)
1153{
1154}
1155
1156template <class KEY, class HASH, class EQUAL>
1157inline
1159 const HASH& hash,
1160 const EQUAL& equal,
1161 bslma::Allocator *basicAllocator)
1162: d_impl(capacity, hash, equal, basicAllocator)
1163{
1164}
1165
1166template <class KEY, class HASH, class EQUAL>
1167template <class INPUT_ITERATOR>
1168inline
1170 INPUT_ITERATOR last,
1171 bslma::Allocator *basicAllocator)
1172: d_impl(0, HASH(), EQUAL(), basicAllocator)
1173{
1174 insert(first, last);
1175}
1176
1177template <class KEY, class HASH, class EQUAL>
1178template <class INPUT_ITERATOR>
1179inline
1181 INPUT_ITERATOR last,
1182 bsl::size_t capacity,
1183 bslma::Allocator *basicAllocator)
1184: d_impl(capacity, HASH(), EQUAL(), basicAllocator)
1185{
1186 insert(first, last);
1187}
1188
1189template <class KEY, class HASH, class EQUAL>
1190template <class INPUT_ITERATOR>
1191inline
1193 INPUT_ITERATOR last,
1194 bsl::size_t capacity,
1195 const HASH& hash,
1196 bslma::Allocator *basicAllocator)
1197: d_impl(capacity, hash, EQUAL(), basicAllocator)
1198{
1199 insert(first, last);
1200}
1201
1202template <class KEY, class HASH, class EQUAL>
1203template <class INPUT_ITERATOR>
1204inline
1206 INPUT_ITERATOR last,
1207 bsl::size_t capacity,
1208 const HASH& hash,
1209 const EQUAL& equal,
1210 bslma::Allocator *basicAllocator)
1211: d_impl(capacity, hash, equal, basicAllocator)
1212{
1213 insert(first, last);
1214}
1215
1216#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1217template <class KEY, class HASH, class EQUAL>
1218inline
1220 bsl::initializer_list<KEY> values,
1221 bslma::Allocator *basicAllocator)
1222: FlatHashSet(values.begin(),
1223 values.end(),
1224 0,
1225 HASH(),
1226 EQUAL(),
1227 basicAllocator)
1228{
1229}
1230
1231template <class KEY, class HASH, class EQUAL>
1232inline
1234 bsl::initializer_list<KEY> values,
1235 bsl::size_t capacity,
1236 bslma::Allocator *basicAllocator)
1237: FlatHashSet(values.begin(),
1238 values.end(),
1239 capacity,
1240 HASH(),
1241 EQUAL(),
1242 basicAllocator)
1243{
1244}
1245
1246template <class KEY, class HASH, class EQUAL>
1247inline
1249 bsl::initializer_list<KEY> values,
1250 bsl::size_t capacity,
1251 const HASH& hash,
1252 bslma::Allocator *basicAllocator)
1253: FlatHashSet(values.begin(),
1254 values.end(),
1255 capacity,
1256 hash,
1257 EQUAL(),
1258 basicAllocator)
1259{
1260}
1261
1262template <class KEY, class HASH, class EQUAL>
1263inline
1265 bsl::initializer_list<KEY> values,
1266 bsl::size_t capacity,
1267 const HASH& hash,
1268 const EQUAL& equal,
1269 bslma::Allocator *basicAllocator)
1270: FlatHashSet(values.begin(),
1271 values.end(),
1272 capacity,
1273 hash,
1274 equal,
1275 basicAllocator)
1276{
1277}
1278#endif
1279
1280template <class KEY, class HASH, class EQUAL>
1281inline
1283 bslma::Allocator *basicAllocator)
1284: d_impl(original.d_impl, basicAllocator)
1285{
1286}
1287
1288template <class KEY, class HASH, class EQUAL>
1289inline
1292: d_impl(bslmf::MovableRefUtil::move(
1293 bslmf::MovableRefUtil::access(original).d_impl))
1294{
1295}
1296
1297template <class KEY, class HASH, class EQUAL>
1298inline
1301 bslma::Allocator *basicAllocator)
1302: d_impl(bslmf::MovableRefUtil::move(
1303 bslmf::MovableRefUtil::access(original).d_impl),
1304 basicAllocator)
1305{
1306}
1307
1308template <class KEY, class HASH, class EQUAL>
1309inline
1313
1314// MANIPULATORS
1315template <class KEY, class HASH, class EQUAL>
1316inline
1318 const FlatHashSet& rhs)
1319{
1320 d_impl = rhs.d_impl;
1321
1322 return *this;
1323}
1324
1325template <class KEY, class HASH, class EQUAL>
1326inline
1329{
1330 FlatHashSet& lvalue = rhs;
1331
1332 d_impl = bslmf::MovableRefUtil::move(lvalue.d_impl);
1333
1334 return *this;
1335}
1336
1337#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1338template <class KEY, class HASH, class EQUAL>
1339inline
1341 bsl::initializer_list<KEY> values)
1342{
1343 FlatHashSet tmp(values.begin(),
1344 values.end(),
1345 0,
1346 d_impl.hash_function(),
1347 d_impl.key_eq(),
1348 d_impl.allocator());
1349
1350 this->swap(tmp);
1351
1352 return *this;
1353}
1354#endif
1355
1356template <class KEY, class HASH, class EQUAL>
1357inline
1359{
1360 d_impl.clear();
1361}
1362
1363#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES
1364template <class KEY, class HASH, class EQUAL>
1365template <class... ARGS>
1368{
1369 return d_impl.emplace(BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...);
1370}
1371
1372template <class KEY, class HASH, class EQUAL>
1373template <class... ARGS>
1377 ARGS&&... args)
1378{
1379 return this->emplace(BSLS_COMPILERFEATURES_FORWARD(ARGS, args)...).first;
1380}
1381
1382#endif
1383
1384
1385template <class KEY, class HASH, class EQUAL>
1386inline
1387bsl::size_t FlatHashSet<KEY, HASH, EQUAL>::erase(const KEY& key)
1388{
1389 return d_impl.erase(key);
1390}
1391
1392template <class KEY, class HASH, class EQUAL>
1393inline
1396{
1397 BSLS_ASSERT_SAFE(position != end());
1398
1399 return d_impl.erase(position);
1400}
1401
1402template <class KEY, class HASH, class EQUAL>
1403inline
1406{
1407 return d_impl.erase(first, last);
1408}
1409
1410template <class KEY, class HASH, class EQUAL>
1411template <class INPUT_ITERATOR>
1412inline
1414 INPUT_ITERATOR last)
1415{
1416 d_impl.insert(first, last);
1417}
1418
1419#if defined(BSLS_COMPILERFEATURES_SUPPORT_GENERALIZED_INITIALIZERS)
1420template <class KEY, class HASH, class EQUAL>
1421inline
1422void FlatHashSet<KEY, HASH, EQUAL>::insert(bsl::initializer_list<KEY> values)
1423{
1424 insert(values.begin(), values.end());
1425}
1426#endif
1427
1428template <class KEY, class HASH, class EQUAL>
1429inline
1430void FlatHashSet<KEY, HASH, EQUAL>::rehash(bsl::size_t minimumCapacity)
1431{
1432 d_impl.rehash(minimumCapacity);
1433}
1434
1435template <class KEY, class HASH, class EQUAL>
1436inline
1437void FlatHashSet<KEY, HASH, EQUAL>::reserve(bsl::size_t numEntries)
1438{
1439 d_impl.reserve(numEntries);
1440}
1441
1442template <class KEY, class HASH, class EQUAL>
1443inline
1445{
1446 d_impl.reset();
1447}
1448
1449 // Aspects
1450
1451template <class KEY, class HASH, class EQUAL>
1452inline
1454{
1455 BSLS_ASSERT_SAFE(allocator() == other.allocator());
1456
1457 d_impl.swap(other.d_impl);
1458}
1459
1460// ACCESSORS
1461template <class KEY, class HASH, class EQUAL>
1462inline
1464{
1465 return d_impl.capacity();
1466}
1467
1468template <class KEY, class HASH, class EQUAL>
1469inline
1471{
1472 return d_impl.contains(key);
1473}
1474
1475template <class KEY, class HASH, class EQUAL>
1476inline
1477bsl::size_t FlatHashSet<KEY, HASH, EQUAL>::count(const KEY& key) const
1478{
1479 return d_impl.count(key);
1480}
1481
1482template <class KEY, class HASH, class EQUAL>
1483inline
1485{
1486 return d_impl.empty();
1487}
1488
1489template <class KEY, class HASH, class EQUAL>
1490inline
1494{
1495 return d_impl.equal_range(key);
1496}
1497
1498template <class KEY, class HASH, class EQUAL>
1499inline
1502{
1503 return d_impl.find(key);
1504}
1505
1506template <class KEY, class HASH, class EQUAL>
1507inline
1509{
1510 return d_impl.hash_function();
1511}
1512
1513template <class KEY, class HASH, class EQUAL>
1514inline
1516{
1517 return d_impl.key_eq();
1518}
1519
1520template <class KEY, class HASH, class EQUAL>
1521inline
1523{
1524 return d_impl.load_factor();
1525}
1526
1527template <class KEY, class HASH, class EQUAL>
1528inline
1530{
1531 return d_impl.max_load_factor();
1532}
1533
1534template <class KEY, class HASH, class EQUAL>
1535inline
1537{
1538 return d_impl.size();
1539}
1540
1541 // Iterators
1542
1543template <class KEY, class HASH, class EQUAL>
1544inline
1547{
1548 return d_impl.begin();
1549}
1550
1551template <class KEY, class HASH, class EQUAL>
1552inline
1555{
1556 return d_impl.cbegin();
1557}
1558
1559template <class KEY, class HASH, class EQUAL>
1560inline
1563{
1564 return d_impl.cend();
1565}
1566
1567template <class KEY, class HASH, class EQUAL>
1568inline
1571{
1572 return d_impl.end();
1573}
1574
1575 // Aspects
1576
1577template <class KEY, class HASH, class EQUAL>
1578inline
1583
1584template <class KEY, class HASH, class EQUAL>
1586 bsl::ostream& stream,
1587 int level,
1588 int spacesPerLevel) const
1589{
1590 if (stream.bad()) {
1591 return stream; // RETURN
1592 }
1593
1594 bslim::Printer printer(&stream, level, spacesPerLevel);
1595
1596 printer.start();
1597
1598 const_iterator iter = begin();
1599 while (iter != end()) {
1600 printer.printValue(*iter);
1601 ++iter;
1602 }
1603
1604 printer.end();
1605
1606 return stream;
1607}
1608
1609} // close package namespace
1610
1611// FREE OPERATORS
1612template <class KEY, class HASH, class EQUAL>
1613inline
1614bool bdlc::operator==(const FlatHashSet<KEY, HASH, EQUAL>& lhs,
1615 const FlatHashSet<KEY, HASH, EQUAL>& rhs)
1616{
1617 return lhs.d_impl == rhs.d_impl;
1618}
1619
1620template <class KEY, class HASH, class EQUAL>
1621inline
1622bool bdlc::operator!=(const FlatHashSet<KEY, HASH, EQUAL>& lhs,
1623 const FlatHashSet<KEY, HASH, EQUAL>& rhs)
1624{
1625 return lhs.d_impl != rhs.d_impl;
1626}
1627
1628template <class KEY, class HASH, class EQUAL>
1629inline
1630bsl::ostream& bdlc::operator<<(bsl::ostream& stream,
1631 const FlatHashSet<KEY, HASH, EQUAL>& set)
1632{
1633 return set.print(stream, 0, -1);
1634}
1635
1636// FREE FUNCTIONS
1637template <class KEY, class HASH, class EQUAL>
1638inline
1639void bdlc::swap(FlatHashSet<KEY, HASH, EQUAL>& a,
1640 FlatHashSet<KEY, HASH, EQUAL>& b)
1641{
1642 bslalg::SwapUtil::swap(&a.d_impl, &b.d_impl);
1643}
1644
1645// ============================================================================
1646// TYPE TRAITS
1647// ============================================================================
1648
1649namespace bslalg {
1650
1651template <class KEY, class HASH, class EQUAL>
1652struct HasStlIterators<bdlc::FlatHashSet<KEY, HASH, EQUAL> >
1654{};
1655
1656} // close namespace bslalg
1657
1658namespace bslma {
1659
1660template <class KEY, class HASH, class EQUAL>
1661struct UsesBslmaAllocator<bdlc::FlatHashSet<KEY, HASH, EQUAL> >
1663{};
1664
1665} // close namespace bslma
1666
1667
1668#endif // End C++11 code
1669
1670#endif
1671
1672// ----------------------------------------------------------------------------
1673// Copyright 2020 Bloomberg Finance L.P.
1674//
1675// Licensed under the Apache License, Version 2.0 (the "License");
1676// you may not use this file except in compliance with the License.
1677// You may obtain a copy of the License at
1678//
1679// http://www.apache.org/licenses/LICENSE-2.0
1680//
1681// Unless required by applicable law or agreed to in writing, software
1682// distributed under the License is distributed on an "AS IS" BASIS,
1683// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1684// See the License for the specific language governing permissions and
1685// limitations under the License.
1686// ----------------------------- END-OF-FILE ----------------------------------
1687
1688/** @} */
1689/** @} */
1690/** @} */
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition bdlc_flathashset.h:564
iterator emplace_hint(const_iterator hint, ARGS &&... args)
bsl::enable_if< bsl::is_convertible< KEY_TYPE, KEY >::value, bsl::pair< const_iterator, bool > >::type insert(BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) value)
Definition bdlc_flathashset.h:840
EQUAL key_eq() const
Definition bdlc_flathashset.h:1515
bsl::size_t count(const KEY &key) const
Definition bdlc_flathashset.h:1477
bsl::pair< iterator, bool > emplace(ARGS &&... args)
EQUAL value_compare
Definition bdlc_flathashset.h:591
const_iterator begin() const
Definition bdlc_flathashset.h:1546
HASH hash_function() const
Definition bdlc_flathashset.h:1508
void reserve(bsl::size_t numEntries)
Definition bdlc_flathashset.h:1437
HASH hasher
Definition bdlc_flathashset.h:592
bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const
Definition bdlc_flathashset.h:1585
const value_type * const_pointer
Definition bdlc_flathashset.h:596
bslma::Allocator * allocator() const
Return the allocator used by this flat hash set to supply memory.
Definition bdlc_flathashset.h:1579
EQUAL key_compare
Definition bdlc_flathashset.h:590
friend void swap(FlatHashSet< K, H, E > &, FlatHashSet< K, H, E > &)
value_type * pointer
Definition bdlc_flathashset.h:595
value_type & reference
Definition bdlc_flathashset.h:593
float load_factor() const
Definition bdlc_flathashset.h:1522
const_iterator find(const KEY &key) const
Definition bdlc_flathashset.h:1501
FlatHashSet()
Definition bdlc_flathashset.h:1120
~FlatHashSet()
Destroy this object and each of its elements.
Definition bdlc_flathashset.h:1310
void clear()
Definition bdlc_flathashset.h:1358
const value_type & const_reference
Definition bdlc_flathashset.h:594
void rehash(bsl::size_t minimumCapacity)
Definition bdlc_flathashset.h:1430
ImplType::const_iterator iterator
Definition bdlc_flathashset.h:597
bsl::size_t size() const
Return the number of elements in this set.
Definition bdlc_flathashset.h:1536
const_iterator cbegin() const
Definition bdlc_flathashset.h:1554
KEY value_type
Definition bdlc_flathashset.h:587
const_iterator cend() const
Definition bdlc_flathashset.h:1562
FlatHashSet & operator=(const FlatHashSet &rhs)
Definition bdlc_flathashset.h:1317
bsl::ptrdiff_t difference_type
Definition bdlc_flathashset.h:589
bsl::size_t capacity() const
Definition bdlc_flathashset.h:1463
bsl::size_t erase(const KEY &key)
Definition bdlc_flathashset.h:1387
void reset()
Definition bdlc_flathashset.h:1444
bsl::enable_if< bsl::is_convertible< KEY_TYPE, KEY >::value, const_iterator >::type insert(const_iterator, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) value)
Definition bdlc_flathashset.h:862
bsl::size_t size_type
Definition bdlc_flathashset.h:588
ImplType::const_iterator const_iterator
Definition bdlc_flathashset.h:598
bool empty() const
Definition bdlc_flathashset.h:1484
float max_load_factor() const
Definition bdlc_flathashset.h:1529
bool contains(const KEY &key) const
Definition bdlc_flathashset.h:1470
bsl::pair< const_iterator, const_iterator > equal_range(const KEY &key) const
Definition bdlc_flathashset.h:1493
const_iterator end() const
Definition bdlc_flathashset.h:1570
KEY key_type
Definition bdlc_flathashset.h:586
Definition bdlc_flathashtable.h:317
void clear()
Definition bdlc_flathashtable.h:1580
bsl::size_t erase(const KEY &key)
Definition bdlc_flathashtable.h:1632
float max_load_factor() const
Definition bdlc_flathashtable.h:2056
const_iterator cbegin() const
Definition bdlc_flathashtable.h:2092
void swap(FlatHashTable &other)
Definition bdlc_flathashtable.h:1918
void reset()
Definition bdlc_flathashtable.h:1806
bsl::pair< iterator, bool > emplace(ARGS &&... args)
iterator find(const KEY &key)
Definition bdlc_flathashtable.h:1741
iterator end()
Definition bdlc_flathashtable.h:1909
bool empty() const
Definition bdlc_flathashtable.h:1970
bsl::enable_if< bsl::is_convertible< ENTRY_TYPE, ENTRY >::value, bsl::pair< iterator, bool > >::type insert(BSLS_COMPILERFEATURES_FORWARD_REF(ENTRY_TYPE) entry)
Definition bdlc_flathashtable.h:564
bslma::Allocator * allocator() const
Return the allocator used by this hash table to supply memory.
Definition bdlc_flathashtable.h:2118
bsl::size_t capacity() const
Definition bdlc_flathashtable.h:1936
bslstl::ForwardIterator< const KEY, IteratorImp > const_iterator
Definition bdlc_flathashtable.h:334
EQUAL key_eq() const
Definition bdlc_flathashtable.h:2032
bool contains(const KEY &key) const
Definition bdlc_flathashtable.h:1943
iterator begin()
Definition bdlc_flathashtable.h:1892
void reserve(bsl::size_t numEntries)
Definition bdlc_flathashtable.h:1787
const_iterator cend() const
Definition bdlc_flathashtable.h:2100
bsl::size_t size() const
Return the number of entries in this table.
Definition bdlc_flathashtable.h:2064
bsl::size_t count(const KEY &key) const
Definition bdlc_flathashtable.h:1962
HASH hash_function() const
Definition bdlc_flathashtable.h:2025
float load_factor() const
Definition bdlc_flathashtable.h:2043
void rehash(bsl::size_t minimumCapacity)
Definition bdlc_flathashtable.h:1766
bsl::pair< iterator, iterator > equal_range(const KEY &key)
Definition bdlc_flathashtable.h:1599
Definition bslstl_pair.h:1210
static void swap(T *a, T *b)
Definition bslalg_swaputil.h:194
Definition bslh_fibonaccibadhashwrapper.h:165
Definition bslim_printer.h:601
void printValue(const TYPE &data) const
Definition bslim_printer.h:1207
void end(bool suppressBracket=false) const
void start(bool suppressBracket=false) const
Definition bslma_allocator.h:457
Definition bslmf_movableref.h:751
#define BSLS_ASSERT_SAFE(X)
Definition bsls_assert.h:1762
#define BSLS_COMPILERFEATURES_FORWARD_REF(T)
Definition bsls_compilerfeatures.h:2012
#define BSLS_COMPILERFEATURES_FORWARD(T, V)
Definition bsls_compilerfeatures.h:2018
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdlc_bitarray.h:503
void swap(BitArray &a, BitArray &b)
bool operator==(const BitArray &lhs, const BitArray &rhs)
bool operator!=(const BitArray &lhs, const BitArray &rhs)
BitArray operator<<(const BitArray &array, bsl::size_t numBits)
T::iterator begin(T &container)
Definition bslstl_iterator.h:1495
T::iterator end(T &container)
Definition bslstl_iterator.h:1523
Definition bdlc_flathashmap.h:1805
Definition balxml_encoderoptions.h:68
Definition bdlbb_blob.h:576
Definition bdlc_flathashset.h:523
static void constructFromKey(ENTRY *entry, bslma::Allocator *allocator, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_TYPE) key)
static const ENTRY & key(const ENTRY &entry)
Return the specified entry.
Definition bdlc_flathashset.h:1108
static void construct(ENTRY *entry, bslma::Allocator *allocator, ARGS &&... args)
Definition bdlc_flathashset.h:1077
Definition bslmf_enableif.h:525
Definition bslstl_equalto.h:311
Definition bslalg_hasstliterators.h:99
static void construct(TARGET_TYPE *address, const ALLOCATOR &allocator)
Definition bslma_constructionutil.h:1243
Definition bslma_usesbslmaallocator.h:343
static MovableRef< t_TYPE > move(t_TYPE &reference) BSLS_KEYWORD_NOEXCEPT
Definition bslmf_movableref.h:1060