// bslstl_hashtable_cpp03.h -*-C++-*- // Automatically generated file. **DO NOT EDIT** #ifndef INCLUDED_BSLSTL_HASHTABLE_CPP03 #define INCLUDED_BSLSTL_HASHTABLE_CPP03 //@PURPOSE: Provide C++03 implementation for bslstl_hashtable.h // //@CLASSES: See bslstl_hashtable.h for list of classes // //@SEE_ALSO: bslstl_hashtable // //@DESCRIPTION: This component is the C++03 translation of a C++11 component, // generated by the 'sim_cpp11_features.pl' program. If the original header // contains any specially delimited regions of C++11 code, then this generated // file contains the C++03 equivalent, i.e., with variadic templates expanded // and rvalue-references replaced by 'bslmf::MovableRef' objects. The header // code in this file is designed to be '#include'd into the original header // when compiling with a C++03 compiler. If there are no specially delimited // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // // Generated on Mon Sep 19 08:58:18 2022 // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifdef COMPILING_BSLSTL_HASHTABLE_H namespace BloombergLP { namespace bslstl { template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR = ::bsl::allocator<typename KEY_CONFIG::ValueType> > class HashTable; template <class FACTORY> class HashTable_ArrayProctor; template <class FACTORY> class HashTable_NodeProctor; template <class FUNCTOR> class HashTable_ComparatorWrapper; template <class FUNCTOR> class HashTable_ComparatorWrapper<const FUNCTOR>; template <class FUNCTOR> class HashTable_ComparatorWrapper<FUNCTOR &>; template <class FUNCTOR> class HashTable_HashWrapper; template <class FUNCTOR> class HashTable_HashWrapper<const FUNCTOR>; template <class FUNCTOR> class HashTable_HashWrapper<FUNCTOR &>; struct HashTable_ImpDetails; struct HashTable_Util; // ====================== // class CallableVariable // ====================== template <class CALLABLE> struct CallableVariable { // This metafunction returns a 'type' that is an alias for 'CALLABLE' // unless that is a function type, in which case it is an alias for // 'CALLABLE &'. This should be used to declare variables of an arbitrary // callable type, typically a template type parameter, that may turn out to // be a function type. Note that this metafunction is necessary as the C++ // language does not allow variables of function type, nor may functions // return a function type. // TYPES typedef typename bsl::conditional< bsl::is_function<CALLABLE>::value, typename bsl::add_lvalue_reference<CALLABLE>::type, CALLABLE>::type type; }; // =========================== // class HashTable_HashWrapper // =========================== template <class FUNCTOR> class HashTable_HashWrapper { // This class provides a wrapper around a functor satisfying the 'Hash' // requirements ({'bslstl_hash'}) such that the function call operator is // always declared as 'const' qualified. // // TBD Provide an optimization for the case of an empty base functor, where // we can safely const_cast want calling the base class operator. // // Note that we would only one class, not two, with C++11 variadic // templates and perfect forwarding, and we could also easily detect // whether or not 'FUNCTOR' provided a const-qualified 'operator()'. private: mutable FUNCTOR d_functor; public: // CREATORS HashTable_HashWrapper(); // Create a 'HashTable_HashWrapper' object wrapping a 'FUNCTOR' that // has its default value. explicit HashTable_HashWrapper(const FUNCTOR& fn); // Create a 'HashTable_HashWrapper' object wrapping a 'FUNCTOR' that is // a copy of the specified 'fn'. // MANIPULATORS void swap(HashTable_HashWrapper &other); // Exchange the value of this object with the specified 'other' object. // ACCESSORS template <class ARG_TYPE> std::size_t operator()(ARG_TYPE& arg) const; // Call the wrapped 'functor' with the specified 'arg' and return the // result. Note that 'ARG_TYPE' will typically be deduced as a 'const' // type. const FUNCTOR& functor() const; // Return a reference providing non-modifiable access to the hash // functor wrapped by this object. }; template <class FUNCTOR> class HashTable_HashWrapper<const FUNCTOR> { // This partial specialization handles 'const' qualified functors, that may // not be stored as a 'mutable' member in the primary template. The need // to wrap such functors diminishes greatly, as there is no need to play // mutable tricks to invoke the function call operator. An alternative to // providing this specialization would be to skip the wrapper entirely if // using a 'const' qualified functor in a 'HashTable'. Note that this type // has a 'const' qualified data member, so is neither assignable nor // swappable. private: const FUNCTOR d_functor; public: // CREATORS HashTable_HashWrapper(); // Create a 'HashTable_HashWrapper' object wrapping a 'FUNCTOR' that // has its default value. explicit HashTable_HashWrapper(const FUNCTOR& fn); // Create a 'HashTable_HashWrapper' object wrapping a 'FUNCTOR' that is // a copy of the specified 'fn'. // ACCESSORS template <class ARG_TYPE> std::size_t operator()(ARG_TYPE& arg) const; // Call the wrapped 'functor' with the specified 'arg' and return the // result. Note that 'ARG_TYPE' will typically be deduced as a 'const' // type. const FUNCTOR& functor() const; // Return a reference providing non-modifiable access to the hash // functor wrapped by this object. }; template <class FUNCTOR> class HashTable_HashWrapper<FUNCTOR &> { // This partial specialization handles 'const' qualified functors, that may // not be stored as a 'mutable' member in the primary template. Note that // the 'FUNCTOR' type itself may be 'const'-qualified, so this one partial // template specialization also handles 'const FUNCTOR&' references. In // order to correctly parse with the reference-binding rules, we drop the // 'const' in front of many of the references to 'FUNCTOR' seen in the // primary template definition. Note that this type has a reference data // member, so is not default constructible, assignable or swappable. private: FUNCTOR& d_functor; public: // CREATORS explicit HashTable_HashWrapper(FUNCTOR& fn); // Create a 'HashTable_HashWrapper' object wrapping a 'FUNCTOR' that is // a copy of the specified 'fn'. // ACCESSORS template <class ARG_TYPE> std::size_t operator()(ARG_TYPE& arg) const; // Call the wrapped 'functor' with the specified 'arg' and return the // result. Note that 'ARG_TYPE' will typically be deduced as a 'const' // type. FUNCTOR& functor() const; // Return a reference providing non-modifiable access to the hash // functor wrapped by this object. }; template <class FUNCTOR> void swap(HashTable_HashWrapper<FUNCTOR> &a, HashTable_HashWrapper<FUNCTOR> &b); // Swap the functor wrapped by the specified 'a' object with the functor // wrapped by the specified 'b' object. // ================================= // class HashTable_ComparatorWrapper // ================================= template <class FUNCTOR> class HashTable_ComparatorWrapper { // This class provides a wrapper around a functor that can compare two // values and return a 'bool', so that the function call operator is always // declared as 'const' qualified. // // TBD Provide an optimization for the case of an empty base functor, where // we can safely const_cast want calling the base class operator. private: mutable FUNCTOR d_functor; public: // CREATORS HashTable_ComparatorWrapper(); // Create a 'HashTable_ComparatorWrapper' object wrapping a 'FUNCTOR' // that has its default value. explicit HashTable_ComparatorWrapper(const FUNCTOR& fn); // Create a 'HashTable_ComparatorWrapper' object wrapping a 'FUNCTOR' // that is a copy of the specified 'fn'. // MANIPULATORS void swap(HashTable_ComparatorWrapper &other); // Exchange the value of this object with the specified 'other' object. // ACCESSORS template <class ARG1_TYPE, class ARG2_TYPE> bool operator()(ARG1_TYPE& arg1, ARG2_TYPE& arg2) const; // Call the wrapped 'functor' with the specified 'arg1' and 'arg2' (in // that order) and return the result. Note that 'ARGn_TYPE' will // typically be deduced as a 'const' type. const FUNCTOR& functor() const; // Return a reference providing non-modifiable access to the hash // functor wrapped by this object. }; template <class FUNCTOR> class HashTable_ComparatorWrapper<const FUNCTOR> { // This partial specialization handles 'const' qualified functors, that may // not be stored as a 'mutable' member in the primary template. The need // to wrap such functors diminishes greatly, as there is no need to play // mutable tricks to invoke the function call operator. An alternative to // providing this specialization would be to skip the wrapper entirely if // using a 'const' qualified functor in a 'HashTable'. Note that this type // has a 'const' qualified data member, so is neither assignable nor // swappable. private: const FUNCTOR d_functor; public: // CREATORS HashTable_ComparatorWrapper(); // Create a 'HashTable_ComparatorWrapper' object wrapping a 'FUNCTOR' // that has its default value. explicit HashTable_ComparatorWrapper(const FUNCTOR& fn); // Create a 'HashTable_ComparatorWrapper' object wrapping a 'FUNCTOR' // that is a copy of the specified 'fn'. // ACCESSORS template <class ARG1_TYPE, class ARG2_TYPE> bool operator()(ARG1_TYPE& arg1, ARG2_TYPE& arg2) const; // Call the wrapped 'functor' with the specified 'arg1' and 'arg2' (in // that order) and return the result. Note that 'ARGn_TYPE' will // typically be deduced as a 'const' type. const FUNCTOR& functor() const; // Return a reference providing non-modifiable access to the hash // functor wrapped by this object. }; template <class FUNCTOR> class HashTable_ComparatorWrapper<FUNCTOR &> { // This partial specialization handles 'const' qualified functors, that may // not be stored as a 'mutable' member in the primary template. Note that // the 'FUNCTOR' type itself may be 'const'-qualified, so this one partial // template specialization also handles 'const FUNCTOR&' references. In // order to correctly parse with the reference-binding rules, we drop the // 'const' in front of many of the references to 'FUNCTOR' seen in the // primary template definition. Note that this type has a reference data // member, so is not default constructible, assignable or swappable. private: FUNCTOR& d_functor; public: // CREATORS explicit HashTable_ComparatorWrapper(FUNCTOR& fn); // Create a 'HashTable_ComparatorWrapper' object wrapping a 'FUNCTOR' // that is a copy of the specified 'fn'. // ACCESSORS template <class ARG1_TYPE, class ARG2_TYPE> bool operator()(ARG1_TYPE& arg1, ARG2_TYPE& arg2) const; // Call the wrapped 'functor' with the specified 'arg1' and 'arg2' (in // that order) and return the result. Note that 'ARGn_TYPE' will // typically be deduced as a 'const' type. FUNCTOR& functor() const; // Return a reference providing non-modifiable access to the hash // functor wrapped by this object. }; template <class FUNCTOR> void swap(HashTable_ComparatorWrapper<FUNCTOR> &lhs, HashTable_ComparatorWrapper<FUNCTOR> &rhs); // Swap the functor wrapped by the specified 'lhs' object with the functor // wrapped by the specified 'rhs' object. // =============== // class HashTable // =============== template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> class HashTable_ImplParameters; template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> class HashTable { // This class template implements a value-semantic container type holding // an unordered sequence of (possibly duplicate) elements, that can be // rapidly accessed using their key, with the constraint on the container // that elements whose keys compare equal according to the specified // 'COMPARATOR' will be stored in a stable, contiguous sequence within the // container. The value type and key type of the elements maintained by a // 'HashTable' are determined by aliases provided through the (template // parameter) type 'KEY_CONFIG'. Elements in a 'HashTable' are stored in // "nodes" that are allocated using an allocator of the specified // 'ALLOCATOR' type (rebound to the node type), and elements are // constructed directly in the node using the allocator as described in the // C++11 standard under the allocator-aware container requirements in // ([container.requirements.general], C++11 23.2.1). The (template // parameter) types 'HASHER' and 'COMPARATOR' shall be 'copy-constructible' // function-objects. 'HASHER' shall support a function call operator // compatible with the following statements: //.. // HASHER hash; // KEY_CONFIG::KeyType key; // std::size_t result = hash(key); //.. // where the definition of the called function meets the requirements of a // hash function, as specified in {'bslstl_hash'}. 'COMPARATOR' shall // support the a function call operator compatible with the following // statements: //.. // COMPARATOR compare; // KEY_CONFIG::KeyType key1, key2; // bool result = compare(key1, key2); //.. // where the definition of the called function defines an equivalence // relationship on keys that is both reflexive and transitive. The // 'HASHER' and 'COMPARATOR' attributes of this class are further // constrained, such for any two objects whose keys compare equal by the // comparator, shall produce the same value from the hasher. // // This class: //: o supports a complete set of *value-semantic* operations //: o except for 'bdex' serialization //: o is *exception-neutral* (agnostic except for the 'at' method) //: o is *alias-safe* //: o is 'const' *thread-safe* // For terminology see {'bsldoc_glossary'}. public: // TYPES typedef ALLOCATOR AllocatorType; typedef ::bsl::allocator_traits<AllocatorType> AllocatorTraits; typedef typename KEY_CONFIG::KeyType KeyType; typedef typename KEY_CONFIG::ValueType ValueType; typedef bslalg::BidirectionalNode<ValueType> NodeType; typedef typename AllocatorTraits::size_type SizeType; private: // PRIVATE TYPES typedef HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR> ImplParameters; typedef bslmf::MovableRefUtil MoveUtil; // This typedef is a convenient alias for the utility associated with // movable references. // CONSISTENCY CHECKS // Assert consistency checks against Machiavellian users, specializing an // allocator for a specific type to have different propagation traits to // the primary template. typedef typename AllocatorTraits::template rebind_traits<NodeType> ReboundTraits; BSLMF_ASSERT( ReboundTraits::propagate_on_container_copy_assignment::value == AllocatorTraits::propagate_on_container_copy_assignment::value); BSLMF_ASSERT( ReboundTraits::propagate_on_container_move_assignment::value == AllocatorTraits::propagate_on_container_move_assignment::value); BSLMF_ASSERT(ReboundTraits::propagate_on_container_swap::value == AllocatorTraits::propagate_on_container_swap::value); private: // DATA ImplParameters d_parameters; // policies governing table behavior bslalg::HashTableAnchor d_anchor; // list root and bucket array SizeType d_size; // number of elements in this table SizeType d_capacity; // max number of elements before a // rehash is required (computed from // 'd_maxLoadFactor') float d_maxLoadFactor; // maximum permitted load factor private: // PRIVATE MANIPULATORS void copyDataStructure(bslalg::BidirectionalLink *cursor); // Copy the sequence of elements from the list starting at the // specified 'cursor' and having 'size' elements. Allocate a bucket // array sufficiently large to store 'size' elements while respecting // the 'maxLoadFactor', and index the copied list into that new array // of hash buckets. This hash table then takes ownership of the list // and bucket array. Note that this method is intended to be called // from copy constructors, which will have assigned some initial values // for the 'size' and other attributes that may not be consistent with // the class invariants until after this method is called. void moveDataStructure(bslalg::BidirectionalLink *cursor); // Recreate the sequence of elements from the list starting at the // specified 'cursor' and having (member) 'd_size' elements, ensuring // that each 'ValueType' object in the source list is move-inserted // into the new sequence. Allocate a bucket array sufficiently large // to store 'd_size' elements, while respecting the 'maxLoadFactor', // and index the new list into that new array of hash buckets. This // hash table then takes ownership of the list and bucket array. Note // that this method is intended to be called from move constructors // (where the source and target allocators do not match), which will // have assigned some initial values for the 'size' and other // attributes that may not be consistent with the class invariants // until after this method completes. If an exception is thrown during // this operation, this object is left in a valid but unspecified // state; it is the caller's responsibility, however, to ensure the // source hash-table is in a valid state if an exception is thrown void quickSwapExchangeAllocators(HashTable *other); // Efficiently exchange the value, functors, and allocator of this // object with those of the specified 'other' object. This method // provides the no-throw exception-safety guarantee. void quickSwapRetainAllocators(HashTable *other); // Efficiently exchange the value and functors this object with those // of the specified 'other' object. This method provides the no-throw // exception-safety guarantee. The behavior is undefined unless this // object was created with the same allocator as 'other'. void rehashIntoExactlyNumBuckets(SizeType newNumBuckets, SizeType capacity); // Re-organize this hash-table to have exactly the specified // 'newNumBuckets', which will then be able to store the specified // 'capacity' number of elements without exceeding the 'maxLoadFactor'. // This operation provides the strong exception guarantee (see // {'bsldoc_glossary'}) unless the 'hasher' throws, in which case this // operation provides the basic exception guarantee, leaving the // hash-table in a valid, but otherwise unspecified (and potentially // empty), state. The behavior is undefined unless // 'size / newNumBuckets <= maxLoadFactor'. Note that the caller is // responsible for correctly computing the 'capacity' supported by the // new number of buckets. This allows for a minor optimization where // the value is computed only once per rehash. void removeAllAndDeallocate(); // Erase all the nodes in this hash-table, and deallocate their memory // via the supplied node-factory. Destroy the array of buckets owned // by this hash-table. If 'd_anchor.bucketAddress()' is the default // bucket address ('HashTable_ImpDetails::defaultBucketAddress'), then // this hash-table does not own its array of buckets, and it will not // be destroyed. void removeAllImp(); // Erase all the nodes in this table and deallocate their memory via // the node factory, without performing the necessary bookkeeping to // reflect such change. Note that this (private) method explicitly // leaves the HashTable in an inconsistent state, and is expected to be // useful when the anchor of this hash table is about to be overwritten // with a new value, or when the hash table is going out of scope and // the extra bookkeeping is not necessary. // PRIVATE ACCESSORS template <class DEDUCED_KEY> bslalg::BidirectionalLink *find(DEDUCED_KEY& key, std::size_t hashValue) const; // Return the address of the first node in this hash table having a key // that compares equal (according to this hash-table's 'comparator') to // the specified 'key'. The behavior is undefined unless the specified // 'hashValue' is the hash code for the 'key' according to the 'hasher' // functor of this hash table. Note that this function's // implementation relies on the supplied 'hashValue' rather than // recomputing it, eliminating some redundant computation for the // public methods. bslalg::HashTableBucket *getBucketAddress(SizeType bucketIndex) const; // Return the address of the bucket at the specified 'bucketIndex' in // bucket array of this hash table. The behavior is undefined unless // 'bucketIndex < this->numBuckets()'. std::size_t hashCodeForNode(bslalg::BidirectionalLink *node) const; // Return the hash code for the element stored in the specified 'node' // using a copy of the hash functor supplied at construction. The // behavior is undefined unless 'node' points to a list-node of type // 'bslalg::BidirectionalNode<KEY_CONFIG::ValueType>'. public: // CREATORS explicit HashTable(const ALLOCATOR& basicAllocator = ALLOCATOR()); // Create an empty hash-table. Optionally specify a 'basicAllocator' // used to supply memory. If 'basicAllocator' is not supplied, a // default-constructed object of the (template parameter) type // 'ALLOCATOR' is used. If the type 'ALLOCATOR' is 'bsl::allocator' // and 'basicAllocator' is not supplied, the currently installed // default allocator is used to supply memory. Use 1.0 for the // 'maxLoadFactor'. Use a default constructed object of the (template // parameter) type 'HASHER' and a default constructed object of the // (template parameter) type 'COMPARATOR' to organize elements in the // table. No memory is allocated unless the 'HASHER' or 'COMPARATOR' // types allocate memory in their default constructor. Note that a // 'bslma::Allocator *' can be supplied for 'basicAllocator' if the // type 'ALLOCATOR' is 'bsl::allocator' (the default). HashTable(const HASHER& hash, const COMPARATOR& compare, SizeType initialNumBuckets, float initialMaxLoadFactor, const ALLOCATOR& basicAllocator = ALLOCATOR()); // Create an empty hash-table using the specified 'hash' and 'compare' // functors to organize elements in the table, which will initially // have at least the specified 'initialNumBuckets' and a // 'maxLoadFactor' of the specified 'initialMaxLoadFactor'. Optionally // specify a 'basicAllocator' used to supply memory. If // 'basicAllocator' is not supplied, a default-constructed object of // the (template parameter) type 'ALLOCATOR' is used. If the type // 'ALLOCATOR' is 'bsl::allocator' and 'basicAllocator' is not // supplied, the currently installed default allocator is used to // supply memory. If this constructor tries to allocate a number of // buckets larger than can be represented by this hash-table's // 'SizeType', a 'std::length_error' exception is thrown. The behavior // is undefined unless '0 < initialMaxLoadFactor'. Note that more than // 'initialNumBuckets' buckets may be created in order to preserve the // bucket allocation strategy of the hash-table (but never fewer). // Also note that a 'bslma::Allocator *' can be supplied for // 'basicAllocator' if the type 'ALLOCATOR' is 'bsl::allocator' (the // default). HashTable(const HashTable& original); // Create a hash-table having the same value (and 'maxLoadFactor') as // the specified 'original' object. Use a copy of 'original.hasher()' // and a copy of 'original.comparator()' to organize elements in this // hash-table. Use the allocator returned by // 'bsl::allocator_traits<ALLOCATOR>:: // select_on_container_copy_construction(original.allocator())' // to allocate memory. This method requires that the 'ValueType' // defined by the (template parameter) type 'KEY_CONFIG' be // 'copy-insertable' into this hash-table (see '{Requirements on // 'KEY_CONFIG'}). Note that this hash-table may have fewer buckets // than 'original', and a correspondingly higher 'loadFactor', so long // as 'maxLoadFactor' is not exceeded. Also note that the created hash // table may have a different 'numBuckets' than 'original', and a // correspondingly different 'loadFactor', as long as 'maxLoadFactor' // is not exceeded. HashTable(BloombergLP::bslmf::MovableRef<HashTable> original); // Create a hash-table having the same value (and 'maxLoadFactor') as // the specified 'original' object by moving (in constant time) the // contents of 'original' to the new hash-table. Use a copy of // 'original.hasher()' and a copy of 'original.comparator()' to // organize elements in this hash-table. The allocator associated with // 'original' is propagated for use in the newly created hash-table. // 'original' is left in a valid but unspecified state. HashTable(const HashTable& original, const ALLOCATOR& basicAllocator); // Create a hash-table having the same value (and 'maxLoadFactor') as // the specified 'original' object that uses the specified // 'basicAllocator' to supply memory. Use a copy of // 'original.hasher()' and a copy of 'original.comparator()' to // organize elements in this hash-table. This method requires that the // 'ValueType' defined by the (template parameter) type 'KEY_CONFIG' be // 'move-insertable' into this hash-table. Note that this hash-table // may have a different 'numBuckets' than 'original', and a // correspondingly different 'loadFactor', as long as 'maxLoadFactor' // is not exceeded. HashTable(BloombergLP::bslmf::MovableRef<HashTable> original, const ALLOCATOR& basicAllocator); // Create a hash table having the same value (and 'maxLoadFactor') as // the specified 'original' object that uses the specified // 'basicAllocator' to supply memory. The contents of 'original' are // moved (in constant time) to the new hash-table if // 'basicAllocator == original.get_allocator()', and are move-inserted // (in linear time) using 'basicAllocator' otherwise. 'original' is // left in a valid but unspecified state. Use a copy of // 'original.hasher()' and a copy of 'original.comparator()' to // organize elements in this hash-table. This method requires that the // 'ValueType' defined by the (template parameter) type 'KEY_CONFIG' be // 'move-insertable' into this hash-table. Note that this hash-table // may have a different 'numBuckets' than 'original', and a // correspondingly different 'loadFactor', as long as 'maxLoadFactor' // is not exceeded. Also note that a 'bslma::Allocator *' can be // supplied for 'basicAllocator' if the (template parameter) // 'ALLOCATOR' is 'bsl::allocator' (the default). ~HashTable(); // Destroy this object. // MANIPULATORS HashTable& operator=(const HashTable& rhs); // Assign to this object the value, hasher, comparator and // 'maxLoadFactor' of the specified 'rhs' object, propagate to this // object the allocator of 'rhs' if the 'ALLOCATOR' type has trait // 'propagate_on_container_copy_assignment', and return a reference // providing modifiable access to this object. This method requires // that the 'ValueType' defined by the (template parameter) type // 'KEY_CONFIG' be 'copy-assignable' and 'copy-insertable' into this // hash-table (see {Requirements on 'KEY_CONFIG'}). This method // requires that the (template parameter) types 'HASHER' and // 'COMPARATOR' be 'copy-constructible' and 'copy-assignable'. Note // that these requirements are modeled after the unordered container // requirements table in the C++11 standard, which is imprecise on this // operation; these requirements might simplify in the future, if the // standard is updated. HashTable& operator=(BloombergLP::bslmf::MovableRef<HashTable> rhs); // Assign to this object the value, hasher, comparator, and // 'maxLoadFactor' of the specified 'rhs' object, propagate to this // object the allocator of 'rhs' if the 'ALLOCATOR' type has trait // 'propagate_on_container_move_assignment', and return a reference // providing modifiable access to this object. If this hash-table and // 'rhs' use the same allocator (after considering the aforementioned // trait), all of the contents of 'rhs' are moved to this hash-table in // constant time; otherwise, all elements in this hash table are either // destroyed or move-assigned to and each additional element in 'rhs' // is move-inserted into this hash-table. 'rhs' is left in a valid but // unspecified state. This method requires that the 'ValueType' // defined by the (template parameter) type 'KEY_CONFIG' be both // 'move-assignable' and 'move-insertable' into this hash-table (see // {Requirements on 'KEY_CONFIG'}). #if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES // {{{ BEGIN GENERATED CODE // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT #define BSLSTL_HASHTABLE_VARIADIC_LIMIT 10 #endif #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_A #define BSLSTL_HASHTABLE_VARIADIC_LIMIT_A BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 0 bslalg::BidirectionalLink *emplace( ); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 1 template <class Args_01> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 2 template <class Args_01, class Args_02> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 3 template <class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 4 template <class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 5 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 6 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 7 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 8 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 9 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 10 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) arguments_10); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 10 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 0 bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 1 template <class Args_01> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 2 template <class Args_01, class Args_02> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 3 template <class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 4 template <class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 5 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 6 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 7 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 8 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 9 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 10 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) arguments_10); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 10 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 0 bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 1 template <class Args_01> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 2 template <class Args_01, class Args_02> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 3 template <class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 4 template <class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 5 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 6 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 7 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 8 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 9 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 10 template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) arguments_10); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_A >= 10 #else // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template <class... Args> bslalg::BidirectionalLink *emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args)... arguments); template <class... Args> bslalg::BidirectionalLink *emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args)... arguments); template <class... Args> bslalg::BidirectionalLink *emplaceIfMissing(bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args)... arguments); // }}} END GENERATED CODE #endif bslalg::BidirectionalLink *insertIfMissing(const KeyType& key); // Insert into this hash-table a newly-created 'ValueType' object, // constructed by forwarding the specified 'key' and a // default-constructed object of the type 'ValueType::second_type', to // the corresponding constructor of 'ValueType', if 'key' does not // already exist in this hash-table. Return the address of the // (possibly newly created and inserted) element in this hash-table // whose key is equivalent to 'key'. If this hash-table contains more // than one element with the supplied 'key', return the first such // element (from the contiguous sequence of elements having a matching // key). Additional buckets are allocated, as needed, to preserve the // invariant 'loadFactor <= maxLoadFactor'. If this function tries to // allocate a number of buckets larger than can be represented by this // hash table's 'SizeType', a 'std::length_error' exception is thrown. // This method requires that the 'ValueType' defined in the (template // parameter) type 'KEY_CONFIG' be 'emplace-constructible' into this // hash-table from a 'pair' of arguments representing the key and // value, respectively (see {Requirements on 'KEY_CONFIG'}); bslalg::BidirectionalLink *insertIfMissing( bool *isInsertedFlag, const ValueType& value); // Insert the specified 'value' into this hash-table if a key // equivalent to that of 'value' does not already exist in this // hash-table. Return the address of the (possibly newly inserted) // element in this hash-table whose key is equivalent to that of // 'value'. If this hash-table contains more than one element with a // matching key, return the first such element (from the contiguous // sequence of elements having a matching key). Additional buckets are // allocated, as needed, to preserve the invariant // 'loadFactor <= maxLoadFactor'. If this function tries to allocate a // number of buckets larger than can be represented by this // hash-table's 'SizeType', a 'std::length_error' exception is thrown. // This method requires that the 'ValueType' defined in the (template // parameter) type 'KEY_CONFIG' be 'copy-insertable' into this // hash-table (see {Requirements on 'KEY_CONFIG'}); bslalg::BidirectionalLink *insertIfMissing( bool *isInsertedFlag, bslmf::MovableRef<ValueType> value); // Insert the specified 'value' into this hash-table if a key // equivalent to that of 'value' does not already exist in this // hash-table. Return the address of the (possibly newly inserted) // element in this hash-table whose key is equivalent to that of // 'value'. 'value' is left in a valid but unspecified state. If this // hash-table contains more than one element with a matching key, // return the first such element (from the contiguous sequence of // elements having a matching key). Additional buckets are allocated, // as needed, to preserve the invariant 'loadFactor <= maxLoadFactor'. // If this function tries to allocate a number of buckets larger than // can be represented by this hash-table's 'SizeType', a // 'std::length_error' exception is thrown. This method requires that // the 'ValueType' defined in the (template parameter) type // 'KEY_CONFIG' be 'move-insertable' into this hash-table (see // {Requirements on 'KEY_CONFIG'}); template <class SOURCE_TYPE> bslalg::BidirectionalLink * insertIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value); // Insert into this hash-table a 'ValueType' object created from the // specified 'value' if a key equivalent to that of such an object does // not already exist in this hash-table. Return the address of the // (possibly newly inserted) element in this hash-table whose key is // equivalent to that of the object created from 'value'. Load 'true' // into the specified 'isInsertedFlag' if a new value was inserted, and // 'false' if an equivalent key was already present. If this // hash-table contains more than one element with an equivalent key, // return the first such element (from the contiguous sequence of // elements having a matching key). Additional buckets are allocated, // as needed, to preserve the invariant 'loadFactor <= maxLoadFactor'. // If this function tries to allocate a number of buckets larger than // can be represented by this hash-table's 'SizeType', a // 'std::length_error' exception is thrown. This method requires that // the 'ValueType' defined in the (template parameter) type // 'KEY_CONFIG' be 'move-insertable' into this hash-table (see // {Requirements on 'KEY_CONFIG'}) and the (template parameter) type // 'SOURCE_TYPE' be implicitly convertible to 'ValueType'. template <class SOURCE_TYPE> bslalg::BidirectionalLink *insert( BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value); // Insert into this hash-table a 'ValueType' object created from the // specified 'value' and return the address of the newly inserted node. // If a key equivalent to that of the newly-created object already // exists in this hash-table, then insert the new object immediately // before the first such element. Additional buckets are allocated, as // needed, to preserve the invariant 'loadFactor <= maxLoadFactor'. If // this function tries to allocate a number of buckets larger than can // be represented by this hash-table's 'SizeType', a // 'std::length_error' exception is thrown. This method requires that // the 'ValueType' defined in the (template parameter) type // 'KEY_CONFIG' be 'move-insertable' into this hash-table (see // {Requirements on 'KEY_CONFIG'}) and the (template parameter) type // 'SOURCE_TYPE' be implicitly convertible to 'ValueType'. Note that // this method is deprecated is provided only to ensure backward // compatibility with existing clients; use the 'emplace' method // instead. template <class SOURCE_TYPE> bslalg::BidirectionalLink *insert( BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value, bslalg::BidirectionalLink *hint); // Insert into this hash-table a 'ValueType' object created from the // specified 'value' (immediately preceding the specified 'hint' if // 'hint' is not null and the key of the node pointed to by 'hint' is // equivalent to that of the newly-created object), and return the // address of the newly inserted node. If 'hint' is null or the key of // the node pointed to by 'hint' is not equivalent to that of the newly // created object, and a key equivalent to that of the newly-created // object already exists in this hash-table, then insert the // newly-created object immediately before the first such element. // Additional buckets will be allocated, as needed, to preserve the // invariant 'loadFactor <= maxLoadFactor'. If this function tries to // allocate a number of buckets larger than can be represented by this // hash-table's 'SizeType', a 'std::length_error' exception is thrown. // This method requires that 'ValueType' defined in the (template // parameter) type 'KEY_CONFIG' be 'move-insertable' into this // hash-table (see {Requirements on 'KEY_CONFIG'}) and the (template // parameter) type 'SOURCE_TYPE' be implicitly convertible to // 'ValueType'. Note that this method is deprecated and is provided // only to ensure backward compatibility with existing clients; use the // 'emplaceWithHint' method instead. // {{{ BEGIN GENERATED CODE // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template <class KEY_ARG, class BDE_OTHER_TYPE> bslalg::BidirectionalLink *insertOrAssign( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); // }}} END GENERATED CODE void rehashForNumBuckets(SizeType newNumBuckets); // Re-organize this hash-table to have at least the specified // 'newNumBuckets', preserving the invariant // 'loadFactor <= maxLoadFactor'. If this function tries to allocate a // number of buckets larger than can be represented by this hash // table's 'SizeType', a 'std::length_error' exception is thrown. This // operation provides the strong exception guarantee (see // {'bsldoc_glossary'}) unless the 'hasher' throws, in which case this // operation provides the basic exception guarantee, leaving the // hash-table in a valid, but otherwise unspecified (and potentially // empty), state. Note that more buckets than requested may be // allocated in order to preserve the bucket allocation strategy of the // hash table (but never fewer). bslalg::BidirectionalLink *remove(bslalg::BidirectionalLink *node); // Remove the specified 'node' from this hash-table, and return the // address of the node immediately after 'node' in this hash-table // (prior to its removal), or a null pointer value if 'node' is the // last node in the table. This method invalidates only iterators and // references to the removed node and previously saved values of the // 'end()' iterator, and preserves the relative order of the nodes not // removed. The behavior is undefined unless 'node' refers to a node // in this hash-table. void removeAll(); // Remove all the elements from this hash-table. Note that this // hash-table is empty after this call, but allocated memory may be // retained for future use. The destructor of each (non-trivial) // element that is remove shall be run. void reserveForNumElements(SizeType numElements); // Re-organize this hash-table to have a sufficient number of buckets // to accommodate at least the specified 'numElements' without // exceeding the 'maxLoadFactor', and ensure that there are sufficient // nodes pre-allocated in this object's node pool. If this function // tries to allocate a number of buckets larger than can be represented // by this hash table's 'SizeType', a 'std::length_error' exception is // thrown. This operation provides the strong exception guarantee (see // {'bsldoc_glossary'}) unless the 'hasher' throws, in which case this // operation provides the basic exception guarantee, leaving the // hash-table in a valid, but otherwise unspecified (and potentially // empty), state. void setMaxLoadFactor(float newMaxLoadFactor); // Set the maximum load factor permitted by this hash table to the // specified 'newMaxLoadFactor', where load factor is the statistical // mean number of elements per bucket. If 'newMaxLoadFactor < // loadFactor', allocate at least enough buckets to re-establish the // invariant 'loadFactor <= maxLoadFactor'. If this function tries to // allocate a number of buckets larger than can be represented by this // hash table's 'SizeType', a 'std::length_error' exception is thrown. // The behavior is undefined unless '0 < maxLoadFactor'. void swap(HashTable& other); // Exchange the value of this object, its 'comparator' functor, its // 'hasher' functor, and its 'maxLoadFactor' with those of the // specified 'other' object. Additionally, if // 'bslstl::AllocatorTraits<ALLOCATOR>::propagate_on_container_swap' is // 'true', then exchange the allocator of this object with that of the // 'other' object, and do not modify either allocator otherwise. This // method provides the no-throw exception-safety guarantee unless any // of the 'comparator' or 'hasher' functors throw when swapped, leaving // both objects in a safely destructible, but otherwise unusable, // state. The operation guarantees 'O[1]' complexity. The behavior is // undefined unless either this object has an allocator that compares // equal to the allocator of 'other', or the trait // 'bslstl::AllocatorTraits<ALLOCATOR>::propagate_on_container_swap' is // 'true'. #if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES // {{{ BEGIN GENERATED CODE // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT #define BSLSTL_HASHTABLE_VARIADIC_LIMIT 10 #endif #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_C #define BSLSTL_HASHTABLE_VARIADIC_LIMIT_C BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 template <class KEY_ARG> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 template <class KEY_ARG, class Args_01> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 template <class KEY_ARG, class Args_01, class Args_02> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 3 template <class KEY_ARG, class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 4 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 5 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 6 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 7 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 8 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 9 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 10 template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) args_10); #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 10 #else // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template <class KEY_ARG, class... Args> bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args)... args); // }}} END GENERATED CODE #endif // ACCESSORS ALLOCATOR allocator() const; // Return a copy of the allocator used to construct this hash table. // Note that this is not the allocator used to allocate elements for // this hash table, which is instead a copy of that allocator rebound // to allocate the nodes used by the internal data structure of this // hash table. const bslalg::HashTableBucket& bucketAtIndex(SizeType index) const; // Return a reference offering non-modifiable access to the // 'HashTableBucket' at the specified 'index' position in the array of // buckets of this table. The behavior is undefined unless 'index < // numBuckets()'. SizeType bucketIndexForKey(const KeyType& key) const; // Return the index of the bucket that would contain all the elements // having the specified 'key'. const COMPARATOR& comparator() const; // Return a reference providing non-modifiable access to the // key-equality comparison functor used by this hash table. SizeType countElementsInBucket(SizeType index) const; // Return the number elements contained in the bucket at the specified // 'index'. Note that this operation has linear run-time complexity // with respect to the number of elements in the indexed bucket. bslalg::BidirectionalLink *elementListRoot() const; // Return the address of the first element in this hash table, or a // null pointer value if this hash table is empty. template <class LOOKUP_KEY> typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate<HASHER, LOOKUP_KEY>::value && BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,LOOKUP_KEY>::value, bslalg::BidirectionalLink *>::type find(const LOOKUP_KEY& key) const // Return the address of a link whose key is equivalent to the // specified 'key' (according to this hash-table's 'comparator'), and a // null pointer value if no such link exists. If this hash-table // contains more than one element having the supplied 'key', return the // first such element (from the contiguous sequence of elements having // the same key). The behavior is undefined unless 'key' is equivalent // to the elements of at most one equivalent-key group. { return bslalg::HashTableImpUtil::findTransparent<KEY_CONFIG>( d_anchor, key, d_parameters.comparator(), d_parameters.hashCodeForKey(key)); } bslalg::BidirectionalLink *find(const KeyType& key) const; // Return the address of a link whose key has the same value as the // specified 'key' (according to this hash-table's 'comparator'), and a // null pointer value if no such link exists. If this hash-table // contains more than one element having the supplied 'key', return the // first such element (from the contiguous sequence of elements having // the same key). bslalg::BidirectionalLink *findEndOfRange( bslalg::BidirectionalLink *first) const; // Return the address of the first node after any nodes holding a value // having the same key as the specified 'first' node (according to this // hash-table's 'comparator'), and a null pointer value if all nodes // following 'first' hold values with the same key as 'first'. The // behavior is undefined unless 'first' is a link in this hash-table. // Note that this hash-table ensures all elements having the same key // form a contiguous sequence. template <class LOOKUP_KEY> typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate<HASHER, LOOKUP_KEY>::value && BloombergLP::bslmf::IsTransparentPredicate<COMPARATOR,LOOKUP_KEY>::value, void>::type findRange(bslalg::BidirectionalLink **first, bslalg::BidirectionalLink **last, const LOOKUP_KEY& key) const // Load into the specified 'first' and 'last' pointers the respective // addresses of the first and last link (in the list of elements owned // by this hash table) where the contained elements have a key that is // equivalent to the specified 'key' using the 'comparator' of this // hash-table, and null pointer values if there are no elements // matching 'key'. The behavior is undefined unless 'key' is // equivalent to the elements of at most one equivalent-key group. // Note that the output values will form a closed range, where both // 'first' and 'last' point to links satisfying the predicate (rather // than a semi-open range where 'last' would point to the element // following the range). Also note that this hash-table ensures all // elements having the same key form a contiguous sequence. // // Note: implemented inline due to Sun CC compilation error. { BSLS_ASSERT_SAFE(first); BSLS_ASSERT_SAFE(last); *first = this->find(key); *last = *first ? this->findEndOfRange(*first) : 0; } void findRange(bslalg::BidirectionalLink **first, bslalg::BidirectionalLink **last, const KeyType& key) const; // Load into the specified 'first' and 'last' pointers the respective // addresses of the first and last link (in the list of elements owned // by this hash table) where the contained elements have a key that // compares equal to the specified 'key' using the 'comparator' of this // hash-table, and null pointer values if there are no elements // matching 'key'. Note that the output values will form a closed // range, where both 'first' and 'last' point to links satisfying the // predicate (rather than a semi-open range where 'last' would point to // the element following the range). Also note that this hash-table // ensures all elements having the same key form a contiguous sequence. bool hasSameValue(const HashTable& other) const; // Return 'true' if the specified 'other' has the same value as this // object, and 'false' otherwise. Two 'HashTable' objects have the // same value if they have the same number of elements, and for every // subset of elements in this object having keys that compare equal // (according to that hash table's 'comparator'), a corresponding // subset of elements exists in the 'other' object, having the same // number of elements, where, for some permutation of the subset in // this object, every element in that subset compares equal (using // 'operator==') to the corresponding element in the 'other' subset. // The behavior is undefined unless both the 'hasher' and 'comparator' // of this object and the 'other' return the same value for every valid // input. Note that this method requires that the 'ValueType' of the // parameterized 'KEY_CONFIG' be "equality-comparable" (see // {Requirements on 'KEY_CONFIG'}). const HASHER& hasher() const; // Return a reference providing non-modifiable access to the hash // functor used by this hash-table. float loadFactor() const; // Return the current load factor for this table. The load factor is // the statistical mean number of elements per bucket. float maxLoadFactor() const; // Return the maximum load factor permitted by this hash table object, // where the load factor is the statistical mean number of elements per // bucket. Note that this hash table will enforce the maximum load // factor by rehashing into a larger array of buckets on any any // insertion operation where a successful insertion would exceed the // maximum load factor. The maximum load factor may actually be less // than the current load factor if the maximum load factor has been // reset, but no insert operations have yet occurred. SizeType maxNumBuckets() const; // Return a theoretical upper bound on the largest number of buckets // that this hash-table could possibly have. Note that there is no // guarantee that the hash-table can successfully maintain that number // of buckets, or even close to that number of buckets without running // out of resources. SizeType maxSize() const; // Return a theoretical upper bound on the largest number of elements // that this hash-table could possibly hold. Note that there is no // guarantee that the hash-table can successfully grow to the returned // size, or even close to that size without running out of resources. SizeType numBuckets() const; // Return the number of buckets contained in this hash table. SizeType rehashThreshold() const; // Return the number of elements this hash table can hold without // requiring a rehash operation in order to respect the // 'maxLoadFactor'. SizeType size() const; // Return the number of elements in this hash table. }; template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void swap(HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& x, HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& y); // Swap both the value, the hasher, the comparator, and the 'maxLoadFactor' // of the specified 'x' object with the value, the hasher, the comparator, // and the 'maxLoadFactor' of the specified 'y' object. Additionally, if // 'bslstl::AllocatorTraits<ALLOCATOR>::propagate_on_container_swap' is // 'true', then exchange the allocator of 'x' with that of 'y', and do not // modify either allocator otherwise. This method guarantees 'O[1]' // complexity if 'x' and 'y' have the same allocator or if the allocators // propagate on swap, otherwise this operation will typically pay the cost // of two copy constructors, which may in turn throw. If the allocators // are the same or propagate, then this method provides the no-throw // exception-safety guarantee unless the 'swap' function of the hasher or // comparator throw. Otherwise this method offers only the basic exception // safety guarantee. template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bool operator==( const HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& lhs, const HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& rhs); // Return 'true' if the specified 'lhs' and 'rhs' objects have the same // value, and 'false' otherwise. Two 'HashTable' objects have the same // value if they have the same number of elements, and for every subset of // elements in 'lhs' having keys that compare equal (according to that hash // table's 'comparator'), a corresponding subset of elements exists in // 'rhs', having the same number of elements, where, for some permutation // of the 'lhs' subset, every element in that subset compares equal (using // 'operator==') to the corresponding element in the 'rhs' subset. The // behavior is undefined unless both the 'hasher' and 'comparator' of 'lhs' // and 'rhs' return the same value for every valid input. Note that this // method requires that the 'ValueType' of the parameterized 'KEY_CONFIG' // be "equality-comparable" (see {Requirements on 'KEY_CONFIG'}). template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bool operator!=( const HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& lhs, const HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& rhs); // Return 'true' if the specified 'lhs' and 'rhs' objects do not have the // same value, and 'false' otherwise. Two 'HashTable' objects do not have // the same value if they do not have the same number of elements, or if, // for any key found in 'lhs', the subset of elements having that key // (according to the hash-table's 'comparator') in 'lhs' either (1) does // not have the same number of elements as the subset of elements having // that key in 'rhs', or (2) there exists no permutation of the 'lhs' // subset where each element compares equal (using 'operator==') to the // corresponding element in the 'rhs' subset. The behavior is undefined // unless both the 'hasher' and 'comparator' of 'lhs' and 'rhs' return the // same value for every valid input. Note that this method requires that // the 'ValueType' of the parameterized 'KEY_CONFIG' be // "equality-comparable" (see {Requirements on 'KEY_CONFIG'}). // ============================ // class HashTable_ArrayProctor // ============================ template <class FACTORY> class HashTable_ArrayProctor { // This class probably already exists in 'bslalg' private: // DATA FACTORY *d_factory_p; bslalg::HashTableAnchor *d_anchor_p; private: // NOT IMPLEMENTED HashTable_ArrayProctor(const HashTable_ArrayProctor&); HashTable_ArrayProctor& operator=(const HashTable_ArrayProctor&); public: // CREATORS HashTable_ArrayProctor(FACTORY *factory, bslalg::HashTableAnchor *anchor); // Create a 'HashTable_ArrayProctor' managing the hash-table data // structure owned by the specified 'anchor' that was created using the // specified 'factory'. ~HashTable_ArrayProctor(); // Destroy the hash-table data structure managed by this proctor and // reclaim all of its resources, unless there was a call to 'release' // this proctor. // MANIPULATORS void release(); // Release from management the object currently managed by this // proctor. If no object is currently being managed, this method has // no effect. }; // =========================== // class HashTable_NodeProctor // =========================== template <class FACTORY> class HashTable_NodeProctor { // This class implements a proctor that, unless its 'release' method has // previously been invoked, automatically deallocates a managed list of // nodes upon destruction by recursively invoking the 'deleteNode' method // of a supplied factory on each node. The (template parameter) type // 'FACTORY' shall be provide a member function that can be called as if it // had the following signature: //.. // void deleteNode(bslalg::BidirectionalLink *node); //.. private: // DATA FACTORY *d_factory_p; bslalg::BidirectionalLink *d_node_p; private: // NOT IMPLEMENTED HashTable_NodeProctor(const HashTable_NodeProctor&); HashTable_NodeProctor& operator=(const HashTable_NodeProctor&); public: // CREATORS HashTable_NodeProctor(FACTORY *factory, bslalg::BidirectionalLink *node); // Create a new node-proctor that conditionally manages the specified // 'node' (if non-zero), and that uses the specified 'factory' to // destroy the node (unless released) upon its destruction. The // behavior is undefined unless 'node' was created by the 'factory'. ~HashTable_NodeProctor(); // Destroy this node proctor, and delete the node that it manages (if // any) by invoking the 'deleteNode' method of the factory supplied at // construction. If no node is currently being managed, this method // has no effect. // MANIPULATORS void release(); // Release from management the node currently managed by this proctor. // If no object is currently being managed, this method has no effect. }; // ========================== // class HashTable_ImpDetails // ========================== struct HashTable_ImpDetails { // This utility 'struct' provides a namespace for functions that are useful // when implementing a hash table. // CLASS METHODS static bslalg::HashTableBucket *defaultBucketAddress(); // Return the address of a statically initialized empty bucket that can // be shared as the (un-owned) bucket array by all empty hash tables. static size_t growBucketsForLoadFactor(size_t *capacity, size_t minElements, size_t requestedBuckets, double maxLoadFactor); // Return the suggested number of buckets to index a linked list that // can hold as many as the specified 'minElements' without exceeding // the specified 'maxLoadFactor', and supporting at least the specified // number of 'requestedBuckets'. Set the specified '*capacity' to the // maximum length of linked list that the returned number of buckets // could index without exceeding the 'maxLoadFactor'. The behavior is // undefined unless '0 < maxLoadFactor', '0 < minElements' and // '0 < requestedBuckets'. static bslma::Allocator *incidentalAllocator(); // Return that address of an allocator that can be used to allocate // temporary storage, but that is neither the default nor global // allocator. Note that this function is intended to support detailed // checks in 'SAFE_2' builds, that may need additional storage for the // evaluation of a validity check on a large data structure, but that // should not change the expected values computed for regular allocator // usage of the component as validated by the test driver. static size_t nextPrime(size_t n); // Return the next prime number greater-than or equal to the specified // 'n' in the increasing sequence of primes chosen to disperse hash // codes across buckets as uniformly as possible. Throw a // 'std::length_error' exception if 'n' is greater than the last prime // number in the sequence. Note that, typically, prime numbers in the // sequence have increasing values that reflect a growth factor (e.g., // each value in the sequence may be, approximately, two times the // preceding value). }; // ==================== // class HashTable_Util // ==================== struct HashTable_Util { // This utility 'struct' provide utilities for initializing and destroying // bucket lists in anchors that are managed by a 'HashTable'. They cannot // migrate down to 'bslalg::HashTableImpUtil' as they rely on the standard // library 'bslma_allocatortraits' for their implementation. // CLASS METHODS template <class TYPE> static void assertNotNullPointer(TYPE&); template <class TYPE> static void assertNotNullPointer(TYPE * const& ptr); template <class TYPE> static void assertNotNullPointer(TYPE * & ptr); // Assert that the passed argument (the specified 'ptr') is not a null // pointer value. Note that this utility is necessary as the // 'HashTable' class template may be instantiated with function // pointers for the hasher or comparator policies, but there is no easy // way to assert in general that the value of a generic type passed to // a function is not a null pointer value. template<class ALLOCATOR> static void destroyBucketArray(bslalg::HashTableBucket *data, std::size_t bucketArraySize, const ALLOCATOR& allocator); // Destroy the specified 'data' array of the specified length // 'bucketArraySize', that was allocated by the specified 'allocator'. template<class ALLOCATOR> static void initAnchor(bslalg::HashTableAnchor *anchor, std::size_t bucketArraySize, const ALLOCATOR& allocator); // Load into the specified 'anchor' a (contiguous) array of buckets of // the specified 'bucketArraySize' using memory supplied by the // specified 'allocator'. The behavior is undefined unless // '0 < bucketArraySize' and '0 == anchor->bucketArraySize()'. Note // that this operation has no effect on 'anchor->listRootAddress()'. }; // ============================== // class HashTable_ImplParameters // ============================== // It looks like the 'CallableVariable' adaptation would be more // appropriately addressed as part of the 'bslalg::FunctorAdapter' wrapper // than intrusively in this component, and in similar ways by any other // container trying to support the full range of standard conforming // functors. Given that our intent is to support standard predicates, it // may be appropriate to handle calling non-'const' 'operator()' overloads // (via a 'mutable' member) too. template <class HASHER> struct HashTable_BaseHasher : bslalg::FunctorAdapter<HashTable_HashWrapper< typename CallableVariable<HASHER>::type> > { }; template <class COMPARATOR> struct HashTable_Comparator : bslalg::FunctorAdapter<HashTable_ComparatorWrapper< typename CallableVariable<COMPARATOR>::type> > { }; template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> class HashTable_ImplParameters : private HashTable_BaseHasher<HASHER>::Type , private HashTable_Comparator<COMPARATOR>::Type { // This class holds all the parameterized parts of a 'HashTable' class, // efficiently exploiting the empty base optimization without adding // unforeseen namespace associations to the 'HashTable' class itself due to // the structural inheritance. // PRIVATE TYPES typedef typename HashTable_BaseHasher<HASHER>::Type BaseHasher; typedef typename HashTable_Comparator<COMPARATOR>::Type BaseComparator; typedef bslmf::MovableRefUtil MoveUtil; // This typedef is a convenient alias for the utility associated with // movable references. // typedefs stolen from HashTable typedef ALLOCATOR AllocatorType; typedef ::bsl::allocator_traits<AllocatorType> AllocatorTraits; typedef typename KEY_CONFIG::ValueType ValueType; typedef bslalg::BidirectionalNode<ValueType> NodeType; public: // PUBLIC TYPES typedef HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR> HashTableType; typedef typename HashTableType::AllocatorTraits:: template rebind_traits<NodeType> ReboundTraits; typedef typename ReboundTraits::allocator_type NodeAllocator; typedef BidirectionalNodePool<typename HashTableType::ValueType, NodeAllocator> NodeFactory; private: // DATA NodeFactory d_nodeFactory; // nested 'struct's have public data by // convention, but should always be // accessed through the public methods. private: // NOT IMPLEMENTED HashTable_ImplParameters(const HashTable_ImplParameters&); // = delete; HashTable_ImplParameters& operator=(const HashTable_ImplParameters&); // = delete; public: // CREATORS explicit HashTable_ImplParameters(const ALLOCATOR& allocator); // Create a 'HashTable_ImplParameters' object having default // constructed 'HASHER' and 'COMPARATOR' functors, and using the // specified 'allocator' to provide a 'BidirectionalNodePool'. HashTable_ImplParameters(const HASHER& hash, const COMPARATOR& compare, const ALLOCATOR& allocator); // Create a 'HashTable_ImplParameters' object having the specified // 'hash' and 'compare' functors, and using the specified 'allocator' // to provide a 'BidirectionalNodePool'. HashTable_ImplParameters(const HashTable_ImplParameters& original, const ALLOCATOR& allocator); // Create a 'HashTable_ImplParameters' object having the same 'hasher' // and 'comparator' attributes as the specified 'original', and // providing a 'BidirectionalNodePool' using the specified 'allocator'. HashTable_ImplParameters( bslmf::MovableRef<HashTable_ImplParameters> original); // Create a 'HashTable_ImplParameters' object with a copy of the // 'hasher' and 'comparator' attributes associated with the specified // 'original' parameters object, and adopting all outstanding memory // allocations and the allocator associated with 'original'. Note that // 'original' is left in a valid but unspecified state. // MANIPULATORS NodeFactory& nodeFactory(); // Return a reference offering modifiable access to the 'nodeFactory' // owned by this object. void quickSwapExchangeAllocators(HashTable_ImplParameters *other); // Efficiently exchange the value, functor, and allocator of this // object with those of the specified 'other' object. This method // provides the no-throw exception-safety guarantee. void quickSwapRetainAllocators(HashTable_ImplParameters *other); // Efficiently exchange the value and functors this object with those // of the specified 'other' object. This method provides the no-throw // exception-safety guarantee. The behavior is undefined unless this // object was created with the same allocator as 'other'. // ACCESSORS const BaseComparator& comparator() const; // Return a reference offering non-modifiable access to the // 'comparator' functor owned by this object. template <class DEDUCED_KEY> std::size_t hashCodeForKey(DEDUCED_KEY& key) const; // Return the hash code for the specified 'key' using a copy of the // hash functor supplied at construction. Note that this function is // provided as a common way to resolve 'const_cast' issues in the case // that the stored hash functor has a function call operator that is // not declared as 'const'. const BaseHasher& hasher() const; // Return a reference offering non-modifiable access to the 'hasher' // functor owned by this object. const NodeFactory& nodeFactory() const; // Return a reference offering non-modifiable access to the // 'nodeFactory' owned by this object. const COMPARATOR& originalComparator() const; // Return a reference offering non-modifiable access to the // 'comparator' functor owned by this object. const HASHER& originalHasher() const; // Return a reference offering non-modifiable access to the 'hasher' // functor owned by this object. }; // ============================================================================ // TEMPLATE AND INLINE FUNCTION DEFINITIONS // ============================================================================ // --------------------------- // class HashTable_HashWrapper // --------------------------- template <class FUNCTOR> inline HashTable_HashWrapper<FUNCTOR>::HashTable_HashWrapper() : d_functor() { } template <class FUNCTOR> inline HashTable_HashWrapper<FUNCTOR>::HashTable_HashWrapper(const FUNCTOR& fn) : d_functor(fn) { } template <class FUNCTOR> template <class ARG_TYPE> inline std::size_t HashTable_HashWrapper<FUNCTOR>::operator()(ARG_TYPE& arg) const { return d_functor(arg); } template <class FUNCTOR> inline const FUNCTOR& HashTable_HashWrapper<FUNCTOR>::functor() const { return d_functor; } template <class FUNCTOR> inline void HashTable_HashWrapper<FUNCTOR>::swap(HashTable_HashWrapper &other) { using std::swap; swap(d_functor, other.d_functor); } // 'const FUNCTOR' partial specialization template <class FUNCTOR> inline HashTable_HashWrapper<const FUNCTOR>::HashTable_HashWrapper() : d_functor() { } template <class FUNCTOR> inline HashTable_HashWrapper<const FUNCTOR>::HashTable_HashWrapper(const FUNCTOR& fn) : d_functor(fn) { } template <class FUNCTOR> template <class ARG_TYPE> inline std::size_t HashTable_HashWrapper<const FUNCTOR>::operator()(ARG_TYPE& arg) const { return d_functor(arg); } template <class FUNCTOR> inline const FUNCTOR& HashTable_HashWrapper<const FUNCTOR>::functor() const { return d_functor; } // 'FUNCTOR &' partial specialization template <class FUNCTOR> inline HashTable_HashWrapper<FUNCTOR &>::HashTable_HashWrapper(FUNCTOR& fn) : d_functor(fn) { } template <class FUNCTOR> template <class ARG_TYPE> inline std::size_t HashTable_HashWrapper<FUNCTOR &>::operator()(ARG_TYPE& arg) const { return d_functor(arg); } template <class FUNCTOR> inline FUNCTOR& HashTable_HashWrapper<FUNCTOR &>::functor() const { return d_functor; } // --------------------------------- // class HashTable_ComparatorWrapper // --------------------------------- template <class FUNCTOR> inline HashTable_ComparatorWrapper<FUNCTOR>::HashTable_ComparatorWrapper() : d_functor() { } template <class FUNCTOR> inline HashTable_ComparatorWrapper<FUNCTOR>:: HashTable_ComparatorWrapper(const FUNCTOR& fn) : d_functor(fn) { } template <class FUNCTOR> template <class ARG1_TYPE, class ARG2_TYPE> inline bool HashTable_ComparatorWrapper<FUNCTOR>::operator()(ARG1_TYPE& arg1, ARG2_TYPE& arg2) const { return d_functor(arg1, arg2); } template <class FUNCTOR> const FUNCTOR& HashTable_ComparatorWrapper<FUNCTOR>::functor() const { return d_functor; } template <class FUNCTOR> inline void HashTable_ComparatorWrapper<FUNCTOR>::swap(HashTable_ComparatorWrapper &other) { using std::swap; swap(d_functor, other.d_functor); } // 'const FUNCTOR' partial specialization template <class FUNCTOR> inline HashTable_ComparatorWrapper<const FUNCTOR>::HashTable_ComparatorWrapper() : d_functor() { } template <class FUNCTOR> inline HashTable_ComparatorWrapper<const FUNCTOR>:: HashTable_ComparatorWrapper(const FUNCTOR& fn) : d_functor(fn) { } template <class FUNCTOR> template <class ARG1_TYPE, class ARG2_TYPE> inline bool HashTable_ComparatorWrapper<const FUNCTOR>::operator()(ARG1_TYPE& arg1, ARG2_TYPE& arg2) const { return d_functor(arg1, arg2); } template <class FUNCTOR> const FUNCTOR& HashTable_ComparatorWrapper<const FUNCTOR>::functor() const { return d_functor; } // 'FUNCTOR &' partial specialization template <class FUNCTOR> inline HashTable_ComparatorWrapper<FUNCTOR &>:: HashTable_ComparatorWrapper(FUNCTOR& fn) : d_functor(fn) { } template <class FUNCTOR> template <class ARG1_TYPE, class ARG2_TYPE> inline bool HashTable_ComparatorWrapper<FUNCTOR &>::operator()(ARG1_TYPE& arg1, ARG2_TYPE& arg2) const { return d_functor(arg1, arg2); } template <class FUNCTOR> inline FUNCTOR& HashTable_ComparatorWrapper<FUNCTOR &>::functor() const { return d_functor; } // --------------------------- // class HashTable_NodeProctor // --------------------------- // CREATORS template <class FACTORY> inline HashTable_NodeProctor<FACTORY>::HashTable_NodeProctor( FACTORY *factory, bslalg::BidirectionalLink *node) : d_factory_p(factory) , d_node_p(node) { BSLS_ASSERT_SAFE(factory); } template <class FACTORY> inline HashTable_NodeProctor<FACTORY>::~HashTable_NodeProctor() { if (d_node_p) { d_factory_p->deleteNode(d_node_p); } } // MANIPULATORS template <class FACTORY> inline void HashTable_NodeProctor<FACTORY>::release() { d_node_p = 0; } // ---------------------------- // class HashTable_ArrayProctor // ---------------------------- // CREATORS template <class FACTORY> inline HashTable_ArrayProctor<FACTORY>::HashTable_ArrayProctor( FACTORY *factory, bslalg::HashTableAnchor *anchor) : d_factory_p(factory) , d_anchor_p(anchor) { BSLS_ASSERT_SAFE(factory); BSLS_ASSERT_SAFE(anchor); } template <class FACTORY> inline HashTable_ArrayProctor<FACTORY>::~HashTable_ArrayProctor() { if (d_anchor_p) { HashTable_Util::destroyBucketArray(d_anchor_p->bucketArrayAddress(), d_anchor_p->bucketArraySize(), d_factory_p->allocator()); bslalg::BidirectionalLink *root = d_anchor_p->listRootAddress(); while (root) { bslalg::BidirectionalLink *next = root->nextLink(); d_factory_p->deleteNode(root); root = next; } } } // MANIPULATORS template <class FACTORY> inline void HashTable_ArrayProctor<FACTORY>::release() { d_anchor_p = 0; } // -------------------- // class HashTable_Util // -------------------- template <class TYPE> inline void HashTable_Util::assertNotNullPointer(TYPE&) { } template <class TYPE> inline void HashTable_Util::assertNotNullPointer(TYPE * const& ptr) { // silence "unused parameter" warning in release builds: (void) ptr; BSLS_ASSERT(ptr); } template <class TYPE> inline void HashTable_Util::assertNotNullPointer(TYPE * & ptr) { // silence "unused parameter" warning in release builds: (void) ptr; BSLS_ASSERT(ptr); } template <class ALLOCATOR> inline void HashTable_Util::destroyBucketArray( bslalg::HashTableBucket *data, std::size_t bucketArraySize, const ALLOCATOR& allocator) { BSLS_ASSERT_SAFE(data); BSLS_ASSERT_SAFE( (1 < bucketArraySize && HashTable_ImpDetails::defaultBucketAddress() != data) || (1 == bucketArraySize && HashTable_ImpDetails::defaultBucketAddress() == data)); typedef ::bsl::allocator_traits<ALLOCATOR> ParamAllocTraits; typedef typename ParamAllocTraits::template rebind_traits<bslalg::HashTableBucket> BucketAllocTraits; typedef typename BucketAllocTraits::allocator_type ArrayAllocator; typedef ::bsl::allocator_traits<ArrayAllocator> ArrayAllocatorTraits; typedef typename ArrayAllocatorTraits::size_type SizeType; BSLS_ASSERT_SAFE(bucketArraySize <= std::numeric_limits<SizeType>::max()); if (HashTable_ImpDetails::defaultBucketAddress() != data) { ArrayAllocator reboundAllocator(allocator); ArrayAllocatorTraits::deallocate( reboundAllocator, data, static_cast<SizeType>(bucketArraySize)); } } template <class ALLOCATOR> inline void HashTable_Util::initAnchor(bslalg::HashTableAnchor *anchor, std::size_t bucketArraySize, const ALLOCATOR& allocator) { BSLS_ASSERT_SAFE(anchor); BSLS_ASSERT_SAFE(0 != bucketArraySize); typedef ::bsl::allocator_traits<ALLOCATOR> ParamAllocTraits; typedef typename ParamAllocTraits::template rebind_traits<bslalg::HashTableBucket> BucketAllocTraits; typedef typename BucketAllocTraits::allocator_type ArrayAllocator; typedef ::bsl::allocator_traits<ArrayAllocator> ArrayAllocatorTraits; typedef typename ArrayAllocatorTraits::size_type SizeType; BSLS_ASSERT_SAFE(bucketArraySize <= std::numeric_limits<SizeType>::max()); ArrayAllocator reboundAllocator(allocator); // This test is necessary to avoid undefined behavior in the non-standard // narrow contract of 'bsl::allocator', although it seems like a reasonable // assumption to pre-empt other allocators too. if (ArrayAllocatorTraits::max_size(reboundAllocator) < bucketArraySize) { bsls::BslExceptionUtil::throwBadAlloc(); } // Conversion to exactly the correct type resolves compiler warnings. The // assertions above are a loose safety check that this conversion can never // overflow - which would require an allocator using a 'size_type' larger // than 'std::size_t', with the requirement that a standard conforming // allocator must use a 'size_type' that is a built-in unsigned integer // type. const SizeType newArraySize = static_cast<SizeType>(bucketArraySize); bslalg::HashTableBucket *data = ArrayAllocatorTraits::allocate( reboundAllocator, newArraySize); std::fill_n(data, bucketArraySize, bslalg::HashTableBucket()); anchor->setBucketArrayAddressAndSize(data, newArraySize); } //------------------------------- // class HashTable_ImplParameters //------------------------------- // CREATORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable_ImplParameters(const ALLOCATOR& allocator) : BaseHasher() , BaseComparator() , d_nodeFactory(allocator) { } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable_ImplParameters(const HASHER& hash, const COMPARATOR& compare, const ALLOCATOR& allocator) : BaseHasher(hash) , BaseComparator(compare) , d_nodeFactory(allocator) { } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable_ImplParameters(const HashTable_ImplParameters& original, const ALLOCATOR& allocator) : BaseHasher(static_cast<const BaseHasher&>(original)) , BaseComparator(static_cast<const BaseComparator&>(original)) , d_nodeFactory(allocator) { } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable_ImplParameters(bslmf::MovableRef<HashTable_ImplParameters> original) : BaseHasher(static_cast<const BaseHasher&>(original)) , BaseComparator(static_cast<const BaseComparator&>(original)) , d_nodeFactory(MoveUtil::move(MoveUtil::access(original).d_nodeFactory)) { } // MANIPULATORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::NodeFactory & HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: nodeFactory() { return d_nodeFactory; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: quickSwapExchangeAllocators(HashTable_ImplParameters *other) { BSLS_ASSERT_SAFE(other); using std::swap; swap(*static_cast<BaseHasher*>(this), *static_cast<BaseHasher*>(other)); swap(*static_cast<BaseComparator*>(this), *static_cast<BaseComparator*>(other)); nodeFactory().swapExchangeAllocators(other->nodeFactory()); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: quickSwapRetainAllocators(HashTable_ImplParameters *other) { BSLS_ASSERT_SAFE(other); using std::swap; swap(*static_cast<BaseHasher*>(this), *static_cast<BaseHasher*>(other)); swap(*static_cast<BaseComparator*>(this), *static_cast<BaseComparator*>(other)); nodeFactory().swapRetainAllocators(other->nodeFactory()); } // ACCESSORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const typename HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::BaseComparator & HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: comparator() const { return *this; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class DEDUCED_KEY> inline std::size_t HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: hashCodeForKey(DEDUCED_KEY& key) const { return static_cast<const BaseHasher &>(*this)(key); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const typename HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::BaseHasher & HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::hasher() const { return *this; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const typename HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::NodeFactory & HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: nodeFactory() const { return d_nodeFactory; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const COMPARATOR& HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::originalComparator() const { return static_cast<const BaseComparator *>(this)->functor(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const HASHER& HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::originalHasher() const { return static_cast<const BaseHasher *>(this)->functor(); } //---------------- // class HashTable //---------------- // CREATORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable(const ALLOCATOR& basicAllocator) : d_parameters(basicAllocator) , d_anchor(HashTable_ImpDetails::defaultBucketAddress(), 1, 0) , d_size() , d_capacity() , d_maxLoadFactor(1.0) { BSLMF_ASSERT(!bsl::is_pointer<HASHER>::value && !bsl::is_pointer<COMPARATOR>::value); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable(const HASHER& hash, const COMPARATOR& compare, SizeType initialNumBuckets, float initialMaxLoadFactor, const ALLOCATOR& basicAllocator) : d_parameters(hash, compare, basicAllocator) , d_anchor(HashTable_ImpDetails::defaultBucketAddress(), 1, 0) , d_size() , d_capacity(0) , d_maxLoadFactor(initialMaxLoadFactor) { BSLS_ASSERT_SAFE(0.0f < initialMaxLoadFactor); if (bsl::is_pointer<HASHER>::value) { HashTable_Util::assertNotNullPointer(hash); } if (bsl::is_pointer<COMPARATOR>::value) { HashTable_Util::assertNotNullPointer(compare); } if (0 != initialNumBuckets) { size_t capacity; // This may be a different type than SizeType. size_t numBuckets = HashTable_ImpDetails::growBucketsForLoadFactor( &capacity, 1, static_cast<size_t>(initialNumBuckets), d_maxLoadFactor); HashTable_Util::initAnchor(&d_anchor, numBuckets, basicAllocator); d_capacity = static_cast<SizeType>(capacity); } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable(const HashTable& original) : d_parameters( original.d_parameters, AllocatorTraits::select_on_container_copy_construction(original.allocator())) , d_anchor(HashTable_ImpDetails::defaultBucketAddress(), 1, 0) , d_size(original.d_size) , d_capacity(0) , d_maxLoadFactor(original.d_maxLoadFactor) { if (0 < d_size) { d_parameters.nodeFactory().reserveNodes(original.d_size); this->copyDataStructure(original.d_anchor.listRootAddress()); } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::HashTable( BloombergLP::bslmf::MovableRef<HashTable> original) : d_parameters(MoveUtil::move(MoveUtil::access(original).d_parameters)) , d_anchor(HashTable_ImpDetails::defaultBucketAddress(), 1, 0) , d_size() , d_capacity() , d_maxLoadFactor(1.0) { HashTable& lvalue = original; using std::swap; swap(d_anchor, lvalue.d_anchor); swap(d_size, lvalue.d_size); swap(d_capacity, lvalue.d_capacity); swap(d_maxLoadFactor, lvalue.d_maxLoadFactor); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable(const HashTable& original, const ALLOCATOR& basicAllocator) : d_parameters(original.d_parameters, basicAllocator) , d_anchor(HashTable_ImpDetails::defaultBucketAddress(), 1, 0) , d_size(original.d_size) , d_capacity(0) , d_maxLoadFactor(original.d_maxLoadFactor) { if (0 < d_size) { d_parameters.nodeFactory().reserveNodes(original.d_size); this->copyDataStructure(original.d_anchor.listRootAddress()); } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: HashTable(bslmf::MovableRef<HashTable> original, const ALLOCATOR& basicAllocator) : d_parameters(MoveUtil::access(original).d_parameters.originalHasher(), MoveUtil::access(original).d_parameters.originalComparator(), basicAllocator) , d_anchor(HashTable_ImpDetails::defaultBucketAddress(), 1, 0) , d_size() , d_capacity() , d_maxLoadFactor(1.0) { HashTable& lvalue = original; if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY( basicAllocator == lvalue.allocator())) { d_parameters.nodeFactory().adopt( MoveUtil::move(lvalue.d_parameters.nodeFactory())); using std::swap; swap(d_anchor, lvalue.d_anchor); swap(d_size, lvalue.d_size); swap(d_capacity, lvalue.d_capacity); swap(d_maxLoadFactor, lvalue.d_maxLoadFactor); } else { d_size = lvalue.d_size; d_maxLoadFactor = lvalue.d_maxLoadFactor; if (0 < d_size) { // 'original' left in the default state bslalg::HashTableAnchor anchor( HashTable_ImpDetails::defaultBucketAddress(), 1, 0); using std::swap; swap(anchor, lvalue.d_anchor); lvalue.d_size = 0; lvalue.d_capacity = 0; lvalue.d_maxLoadFactor = 1.0f; HashTable_ArrayProctor<typename ImplParameters::NodeFactory> arrayProctor(&lvalue.d_parameters.nodeFactory(), &anchor); d_parameters.nodeFactory().reserveNodes(d_size); this->moveDataStructure(anchor.listRootAddress()); // 'arrayProctor' will care of deleting the nodes } } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::~HashTable() { #if defined(BDE_BUILD_TARGET_SAFE_2) // ASSERT class invariant only in SAFE_2 builds. Note that we specifically // use the MallocFree allocator, rather than allowing the default allocator // to supply memory to this state-checking function, in case the object // allocator *is* the default allocator, and so may be restricted during // testing. This would cause the test below to fail by throwing a bad // allocation exception, and so result in a throwing destructor. While the // MallocFree allocator might also run out of resources, that is not the // kind of catastrophic failure we are concerned with handling in an // invariant check that runs only in SAFE_2 builds from a destructor. BSLS_ASSERT_SAFE(bslalg::HashTableImpUtil::isWellFormed<KEY_CONFIG>( this->d_anchor, this->d_parameters.hasher(), HashTable_ImpDetails::incidentalAllocator())); #endif this->removeAllAndDeallocate(); } // PRIVATE MANIPULATORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::copyDataStructure( bslalg::BidirectionalLink *cursor) { BSLS_ASSERT(0 != cursor); BSLS_ASSERT(0 < d_size); // This function will completely replace 'this->d_anchor's state. It is // the caller's responsibility to ensure this will not leak resources owned // only by the previous state, such as the linked list. // Allocate an appropriate number of buckets size_t capacity; size_t numBuckets = HashTable_ImpDetails::growBucketsForLoadFactor( &capacity, static_cast<size_t>(d_size), 2, d_maxLoadFactor); d_anchor.setListRootAddress(0); HashTable_Util::initAnchor(&d_anchor, numBuckets, this->allocator()); // create a proctor for d_anchor's allocated array, and the list to follow. HashTable_ArrayProctor<typename ImplParameters::NodeFactory> arrayProctor(&d_parameters.nodeFactory(), &d_anchor); d_capacity = static_cast<SizeType>(capacity); do { // Computing hash code depends on user-supplied code, and may throw. // Therefore, obtain the hash code from the node we are about to copy, // before any memory is allocated, so there is no risk of leaking an // object. The hash code must be the same for both elements. size_t hashCode = this->hashCodeForNode(cursor); bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().cloneNode(*cursor); bslalg::HashTableImpUtil::insertAtBackOfBucket(&d_anchor, newNode, hashCode); } while (0 != (cursor = cursor->nextLink())); // release the proctor arrayProctor.release(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::moveDataStructure( bslalg::BidirectionalLink *cursor) { BSLS_ASSERT(0 != cursor); BSLS_ASSERT(0 < d_size); // This function will completely replace 'this->d_anchor's state. It is // the caller's responsibility to ensure this will not leak resources owned // only by the previous state, such as the linked list. // Allocate an appropriate number of buckets size_t capacity; size_t numBuckets = HashTable_ImpDetails::growBucketsForLoadFactor( &capacity, static_cast<size_t>(d_size), 2, d_maxLoadFactor); d_anchor.setListRootAddress(0); HashTable_Util::initAnchor(&d_anchor, numBuckets, this->allocator()); d_capacity = static_cast<SizeType>(capacity); // create a proctor for d_anchor's allocated array, and the list to follow. HashTable_ArrayProctor<typename ImplParameters::NodeFactory> arrayProctor(&d_parameters.nodeFactory(), &d_anchor); do { // Computing hash code depends on user-supplied code, and may throw. // Therefore, obtain the hash code from the node we are about to copy, // before any memory is allocated, so there is no risk of leaking an // object. The hash code must be the same for both elements. size_t hashCode = this->hashCodeForNode(cursor); bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().moveIntoNewNode(cursor); bslalg::HashTableImpUtil::insertAtBackOfBucket(&d_anchor, newNode, hashCode); } while (0 != (cursor = cursor->nextLink())); // release the proctor arrayProctor.release(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: quickSwapExchangeAllocators(HashTable *other) { BSLS_ASSERT_SAFE(other); d_parameters.quickSwapExchangeAllocators(&other->d_parameters); using std::swap; swap(d_anchor, other->d_anchor); swap(d_size, other->d_size); swap(d_capacity, other->d_capacity); swap(d_maxLoadFactor, other->d_maxLoadFactor); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: quickSwapRetainAllocators(HashTable *other) { BSLS_ASSERT_SAFE(other); BSLS_ASSERT_SAFE(this->allocator() == other->allocator()); d_parameters.quickSwapRetainAllocators(&other->d_parameters); using std::swap; swap(d_anchor, other->d_anchor); swap(d_size, other->d_size); swap(d_capacity, other->d_capacity); swap(d_maxLoadFactor, other->d_maxLoadFactor); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: rehashIntoExactlyNumBuckets(SizeType newNumBuckets, SizeType capacity) { class Proctor { // An object of this proctor class guarantees that, if an exception is // thrown by a user-supplied hash functor, the container remains in a // valid, usable (but unspecified) state. In fact, that state will be // empty, as there is no reliable way to re-index a bucket array if the // hash functor is throwing, and the array is potentially corrupted // following a failed ImpUtil::rehash call. private: HashTable *d_table_p; bslalg::HashTableAnchor *d_originalAnchor_p; bslalg::HashTableAnchor *d_newAnchor_p; #if !defined(BSLS_PLATFORM_CMP_MSVC) // Microsoft warns if these methods are declared private. private: // NOT IMPLEMENTED Proctor(const Proctor&); // = delete; Proctor& operator=(const Proctor&); // = delete; #endif public: // CREATORS Proctor(HashTable *table, bslalg::HashTableAnchor *originalAnchor, bslalg::HashTableAnchor *newAnchor) : d_table_p(table) , d_originalAnchor_p(originalAnchor) , d_newAnchor_p(newAnchor) { BSLS_ASSERT_SAFE(table); BSLS_ASSERT_SAFE(originalAnchor); BSLS_ASSERT_SAFE(newAnchor); } ~Proctor() { if (d_originalAnchor_p) { // Not dismissed, and the newAnchor now holds the correct // list-root. d_originalAnchor_p->setListRootAddress( d_newAnchor_p->listRootAddress()); d_table_p->removeAll(); } // Always destroy the spare anchor's bucket array at the end of // scope. On a non-exceptional run, this will effectively be the // original bucket-array, as the anchors are swapped. HashTable_Util::destroyBucketArray( d_newAnchor_p->bucketArrayAddress(), d_newAnchor_p->bucketArraySize(), d_table_p->allocator()); } // MANIPULATORS void dismiss() { d_originalAnchor_p = 0; } }; // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Now that 'anchor' is not default constructible, we take a copy of the // anchor in the table. Would it be better for 'initAnchor' to be replaced // with a 'createArrayOfEmptyBuckets' function, and we use the result to // construct the 'newAnchor'? bslalg::HashTableAnchor newAnchor(0, 0, 0); HashTable_Util::initAnchor(&newAnchor, static_cast<size_t>(newNumBuckets), this->allocator()); Proctor cleanUpIfUserHashThrows(this, &d_anchor, &newAnchor); if (d_anchor.listRootAddress()) { bslalg::HashTableImpUtil::rehash<KEY_CONFIG>( &newAnchor, this->d_anchor.listRootAddress(), this->d_parameters.hasher()); } cleanUpIfUserHashThrows.dismiss(); d_anchor.swap(newAnchor); d_capacity = capacity; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::removeAllAndDeallocate() { this->removeAllImp(); HashTable_Util::destroyBucketArray(d_anchor.bucketArrayAddress(), d_anchor.bucketArraySize(), this->allocator()); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::removeAllImp() { typedef bslalg::BidirectionalLink BidirectionalLink; // Doing too much book-keeping of hash table - look for a more efficient // dispose-as-we-walk, that simply resets table.Anchor.next = 0, and // assigns the buckets index all null pointers if (BidirectionalLink *root = d_anchor.listRootAddress()) { BidirectionalLink *next; do { next = root->nextLink(); d_parameters.nodeFactory().deleteNode( static_cast<NodeType *>(root)); } while(0 != (root = next)); } } // PRIVATE ACCESSORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class DEDUCED_KEY> inline bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::find( DEDUCED_KEY& key, std::size_t hashValue) const { return bslalg::HashTableImpUtil::find<KEY_CONFIG>( d_anchor, key, d_parameters.comparator(), hashValue); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline bslalg::HashTableBucket * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::getBucketAddress( SizeType bucketIndex) const { BSLS_ASSERT_SAFE(bucketIndex < this->numBuckets()); return d_anchor.bucketArrayAddress() + bucketIndex; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline std::size_t HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::hashCodeForNode( bslalg::BidirectionalLink *node) const { BSLS_ASSERT_SAFE(node); return d_parameters.hashCodeForKey( bslalg::HashTableImpUtil::extractKey<KEY_CONFIG>(node)); } // MANIPULATORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::operator=( const HashTable& rhs) { if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &rhs)) { if (AllocatorTraits::propagate_on_container_copy_assignment::value) { HashTable other(rhs, rhs.allocator()); quickSwapExchangeAllocators(&other); } else { HashTable other(rhs, this->allocator()); quickSwapRetainAllocators(&other); } } return *this; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::operator=( bslmf::MovableRef<HashTable> rhs) { HashTable& lvalue = rhs; if (BSLS_PERFORMANCEHINT_PREDICT_LIKELY(this != &lvalue)) { if (allocator() == lvalue.allocator()) { HashTable other(MoveUtil::move(lvalue)); quickSwapRetainAllocators(&other); } else if ( AllocatorTraits::propagate_on_container_move_assignment::value) { HashTable other(MoveUtil::move(lvalue)); quickSwapExchangeAllocators(&other); } else { HashTable other(MoveUtil::move(lvalue), allocator()); quickSwapRetainAllocators(&other); } } return *this; } #if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES // {{{ BEGIN GENERATED CODE // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT #define BSLSTL_HASHTABLE_VARIADIC_LIMIT 10 #endif #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_D #define BSLSTL_HASHTABLE_VARIADIC_LIMIT_D BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( ) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( ); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) arguments_10) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09), BSLS_COMPILERFEATURES_FORWARD(Args_10, arguments_10)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( ); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) arguments_10) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09), BSLS_COMPILERFEATURES_FORWARD(Args_10, arguments_10)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( ); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) arguments_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) arguments_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) arguments_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) arguments_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) arguments_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) arguments_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) arguments_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) arguments_10) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09), BSLS_COMPILERFEATURES_FORWARD(Args_10, arguments_10)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 #else // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class... Args> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args)... arguments) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); if (!position) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, position); } nodeProctor.release(); ++d_size; return newNode; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class... Args> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceWithHint( bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args)... arguments) { typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); if (!hint || !d_parameters.comparator()(ImpUtil::extractKey<KEY_CONFIG>(newNode), ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); } if (!hint) { ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); } else { ImpUtil::insertAtPosition(&d_anchor, newNode, hashCode, hint); } nodeProctor.release(); ++d_size; return newNode; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class... Args> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::emplaceIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(Args)... arguments) { BSLS_ASSERT(isInsertedFlag); typedef bslalg::HashTableImpUtil ImpUtil; if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } bslalg::BidirectionalLink *newNode = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(Args, arguments)...); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), newNode); size_t hashCode = this->d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(newNode)); bslalg::BidirectionalLink *position = this->find( ImpUtil::extractKey<KEY_CONFIG>(newNode), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } ImpUtil::insertAtFrontOfBucket(&d_anchor, newNode, hashCode); nodeProctor.release(); ++d_size; position = newNode; } return position; } // }}} END GENERATED CODE #endif template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insertIfMissing( const KeyType& key) { size_t hashCode = this->d_parameters.hashCodeForKey(key); bslalg::BidirectionalLink *position = this->find(key, hashCode); if (!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } typedef typename ValueType::second_type MappedType; // TBD: make 'this->allocator()' return the allocator by reference with // modifiable access rather than by value. AllocatorType alloc = this->allocator(); bsls::ObjectBuffer<MappedType> defaultMapped; AllocatorTraits::construct(alloc, defaultMapped.address()); bslma::DestructorGuard<MappedType> mappedGuard( defaultMapped.address()); #if defined(BSLMF_MOVABLEREF_USES_RVALUE_REFERENCES) position = d_parameters.nodeFactory().emplaceIntoNewNode( key, MoveUtil::move(defaultMapped.object())); #else position = d_parameters.nodeFactory().emplaceIntoNewNode( key, defaultMapped.object()); #endif bslalg::HashTableImpUtil::insertAtFrontOfBucket(&d_anchor, position, hashCode); ++d_size; } return position; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insertIfMissing( bool *isInsertedFlag, const ValueType& value) { BSLS_ASSERT(isInsertedFlag); size_t hashCode = this->d_parameters.hashCodeForKey( KEY_CONFIG::extractKey(value)); bslalg::BidirectionalLink *position = this->find( KEY_CONFIG::extractKey(value), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } position = d_parameters.nodeFactory().emplaceIntoNewNode(value); bslalg::HashTableImpUtil::insertAtFrontOfBucket(&d_anchor, position, hashCode); ++d_size; } return position; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insertIfMissing( bool *isInsertedFlag, bslmf::MovableRef<ValueType> value) { ValueType& lvalue = value; BSLS_ASSERT(isInsertedFlag); size_t hashCode = this->d_parameters.hashCodeForKey( KEY_CONFIG::extractKey(lvalue)); bslalg::BidirectionalLink *position = this->find( KEY_CONFIG::extractKey(lvalue), hashCode); *isInsertedFlag = (!position); if(!position) { if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } position = d_parameters.nodeFactory().emplaceIntoNewNode( MoveUtil::move(lvalue)); bslalg::HashTableImpUtil::insertAtFrontOfBucket(&d_anchor, position, hashCode); ++d_size; } return position; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class SOURCE_TYPE> inline bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insertIfMissing( bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value) { BSLS_ASSERT(isInsertedFlag); return emplaceIfMissing(isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD(SOURCE_TYPE, value)); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class SOURCE_TYPE> inline bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insert( BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value) { return emplace(BSLS_COMPILERFEATURES_FORWARD(SOURCE_TYPE, value)); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class SOURCE_TYPE> inline bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insert( BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value, bslalg::BidirectionalLink *hint) { return emplaceWithHint(hint, BSLS_COMPILERFEATURES_FORWARD(SOURCE_TYPE, value)); } // {{{ BEGIN GENERATED CODE // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class BDE_OTHER_TYPE> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::insertOrAssign( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { static_cast<NodeType *>(hint)->value().second = BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj); *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } // }}} END GENERATED CODE template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::rehashForNumBuckets( SizeType newNumBuckets) { if (newNumBuckets > this->numBuckets()) { // Compute a "good" number of buckets, e.g., pick a prime number from a // sorted array of exponentially increasing primes. size_t capacity; SizeType numBuckets = static_cast<SizeType>( HashTable_ImpDetails::growBucketsForLoadFactor( &capacity, d_size + 1u, static_cast<size_t>(newNumBuckets), d_maxLoadFactor)); this->rehashIntoExactlyNumBuckets(numBuckets, static_cast<SizeType>(capacity)); } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::remove( bslalg::BidirectionalLink *node) { BSLS_ASSERT_SAFE(node); BSLS_ASSERT_SAFE(node->previousLink() || d_anchor.listRootAddress() == node); bslalg::BidirectionalLink *result = node->nextLink(); bslalg::HashTableImpUtil::remove(&d_anchor, node, hashCodeForNode(node)); --d_size; d_parameters.nodeFactory().deleteNode(static_cast<NodeType *>(node)); return result; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::removeAll() { this->removeAllImp(); if (HashTable_ImpDetails::defaultBucketAddress() != d_anchor.bucketArrayAddress()) { std::memset(d_anchor.bucketArrayAddress(), 0, sizeof(bslalg::HashTableBucket) * d_anchor.bucketArraySize()); } d_anchor.setListRootAddress(0); d_size = 0; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::reserveForNumElements( SizeType numElements) { if (numElements < 1) { // Return avoids undefined behavior in node factory. return; // RETURN } if (numElements > d_capacity) { // Compute a "good" number of buckets, e.g., pick a prime number from a // sorted array of exponentially increasing primes. size_t capacity; SizeType numBuckets = static_cast<SizeType>( HashTable_ImpDetails::growBucketsForLoadFactor( &capacity, numElements, static_cast<size_t>(this->numBuckets()), d_maxLoadFactor)); this->rehashIntoExactlyNumBuckets(numBuckets, static_cast<SizeType>(capacity)); } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::setMaxLoadFactor( float newMaxLoadFactor) { BSLS_ASSERT_SAFE(0.0f < newMaxLoadFactor); size_t capacity; SizeType numBuckets = static_cast<SizeType>( HashTable_ImpDetails::growBucketsForLoadFactor( &capacity, std::max<SizeType>(d_size, 1u), static_cast<size_t>(this->numBuckets()), newMaxLoadFactor)); this->rehashIntoExactlyNumBuckets(numBuckets, static_cast<SizeType>(capacity)); // Always set this last, as there is potential to throw exceptions above. d_maxLoadFactor = newMaxLoadFactor; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::swap(HashTable& other) { // This trait should perform 'if' at compile-time. if (AllocatorTraits::propagate_on_container_swap::value) { quickSwapExchangeAllocators(&other); } else { // C++11 behavior: undefined for unequal allocators // BSLS_ASSERT(allocator() == other.allocator()); BSLS_ASSERT(d_parameters.nodeFactory().allocator() == other.d_parameters.nodeFactory().allocator()); quickSwapRetainAllocators(&other); } } #if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES // {{{ BEGIN GENERATED CODE // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT #define BSLSTL_HASHTABLE_VARIADIC_LIMIT 10 #endif #ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_F #define BSLSTL_HASHTABLE_VARIADIC_LIMIT_F BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 0 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple()); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType()); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 0 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 1 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 1 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 2 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 2 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 3 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 3 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 4 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 4 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 5 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 5 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 6 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 6 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 7 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 7 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 8 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 8 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 9 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 9 #if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 10 template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class Args_01, class Args_02, class Args_03, class Args_04, class Args_05, class Args_06, class Args_07, class Args_08, class Args_09, class Args_10> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) args_02, BSLS_COMPILERFEATURES_FORWARD_REF(Args_03) args_03, BSLS_COMPILERFEATURES_FORWARD_REF(Args_04) args_04, BSLS_COMPILERFEATURES_FORWARD_REF(Args_05) args_05, BSLS_COMPILERFEATURES_FORWARD_REF(Args_06) args_06, BSLS_COMPILERFEATURES_FORWARD_REF(Args_07) args_07, BSLS_COMPILERFEATURES_FORWARD_REF(Args_08) args_08, BSLS_COMPILERFEATURES_FORWARD_REF(Args_09) args_09, BSLS_COMPILERFEATURES_FORWARD_REF(Args_10) args_10) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09), BSLS_COMPILERFEATURES_FORWARD(Args_10, args_10))); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType( BSLS_COMPILERFEATURES_FORWARD(Args_01, args_01), BSLS_COMPILERFEATURES_FORWARD(Args_02, args_02), BSLS_COMPILERFEATURES_FORWARD(Args_03, args_03), BSLS_COMPILERFEATURES_FORWARD(Args_04, args_04), BSLS_COMPILERFEATURES_FORWARD(Args_05, args_05), BSLS_COMPILERFEATURES_FORWARD(Args_06, args_06), BSLS_COMPILERFEATURES_FORWARD(Args_07, args_07), BSLS_COMPILERFEATURES_FORWARD(Args_08, args_08), BSLS_COMPILERFEATURES_FORWARD(Args_09, args_09), BSLS_COMPILERFEATURES_FORWARD(Args_10, args_10))); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } #endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 10 #else // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> template <class KEY_ARG, class... Args> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(Args)... args) { typedef bslalg::HashTableImpUtil ImpUtil; const KEY_ARG& lvalue = key; const size_t hashCode = this->d_parameters.hashCodeForKey(lvalue); if (!hint || !d_parameters.comparator()(lvalue, ImpUtil::extractKey<KEY_CONFIG>(hint))) { hint = this->find(lvalue, hashCode); } if (hint) { *isInsertedFlag = false; return hint; } if (d_size >= d_capacity) { this->rehashForNumBuckets(numBuckets() * 2); } #if defined(BSLS_LIBRARYFEATURES_HAS_CPP11_PAIR_PIECEWISE_CONSTRUCTOR) hint = d_parameters.nodeFactory().emplaceIntoNewNode( std::piecewise_construct, std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key)), std::forward_as_tuple(BSLS_COMPILERFEATURES_FORWARD(Args, args)...)); #else typedef typename ValueType::second_type MappedType; hint = d_parameters.nodeFactory().emplaceIntoNewNode( BSLS_COMPILERFEATURES_FORWARD(KEY_ARG, key), MappedType(BSLS_COMPILERFEATURES_FORWARD(Args, args)...)); #endif HashTable_NodeProctor<typename ImplParameters::NodeFactory> nodeProctor(&d_parameters.nodeFactory(), hint); ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); nodeProctor.release(); ++d_size; *isInsertedFlag = true; return hint; } // }}} END GENERATED CODE #endif // ACCESSORS template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline ALLOCATOR HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>:: allocator() const { return d_parameters.nodeFactory().allocator(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const bslalg::HashTableBucket& HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::bucketAtIndex( SizeType index) const { BSLS_ASSERT_SAFE(index < this->numBuckets()); return d_anchor.bucketArrayAddress()[index]; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::bucketIndexForKey( const KeyType& key) const { typedef typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType SizeType; // The following cast will not discard any useful bits, unless 'SizeType' // is larger than 'size_t', as the bucket computation takes a mod on the // supplied number of buckets. We use the following 'BSLMF_ASSERT' to // assert that assumption at compile time. BSLMF_ASSERT(sizeof(SizeType) <= sizeof(size_t)); size_t hashCode = this->d_parameters.hashCodeForKey(key); return static_cast<SizeType>(bslalg::HashTableImpUtil::computeBucketIndex( hashCode, d_anchor.bucketArraySize())); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const COMPARATOR& HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::comparator() const { return d_parameters.originalComparator(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::countElementsInBucket( SizeType index) const { BSLS_ASSERT_SAFE(index < this->numBuckets()); return static_cast<SizeType>(bucketAtIndex(index).countElements()); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::elementListRoot() const { return d_anchor.listRootAddress(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::find( const KeyType& key) const { return bslalg::HashTableImpUtil::find<KEY_CONFIG>( d_anchor, key, d_parameters.comparator(), d_parameters.hashCodeForKey(key)); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bslalg::BidirectionalLink * HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::findEndOfRange( bslalg::BidirectionalLink *first) const { BSLS_ASSERT_SAFE(first); typedef bslalg::HashTableImpUtil ImpUtil; // The reference to the Key passed to the functor is only optionally // const-qualified. We must be sure to hold a reference with the correct // qualification. typedef typename bslalg::HashTableImpUtil_ExtractKeyResult<KEY_CONFIG>::Type KeyRef; KeyRef k = ImpUtil::extractKey<KEY_CONFIG>(first); while (0 != (first = first->nextLink()) && d_parameters.comparator()(k,ImpUtil::extractKey<KEY_CONFIG>(first))) { // This loop body is intentionally left blank. } return first; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::findRange( bslalg::BidirectionalLink **first, bslalg::BidirectionalLink **last, const KeyType& key) const { BSLS_ASSERT_SAFE(first); BSLS_ASSERT_SAFE(last); *first = this->find(key); *last = *first ? this->findEndOfRange(*first) : 0; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> bool HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::hasSameValue( const HashTable& other) const { // TBD: The template bloat of this function can be significantly reduced. //.. // What matters is that the two hash tables: // i/ are the same size // ii/ have lists that are permutations of each other according to the // element's 'operator==' // This means that the implementation should be independent of all four // template parameters, but will depend on VALUE_TYPE deduced from the // KEY_CONFIG. Otherwise, after the initial size comparison, the rest // depends only on the anchors. //.. typedef typename KEY_CONFIG::ValueType ValueType; typedef typename ::bsl::allocator_traits<ALLOCATOR>::size_type SizeType; typedef bslalg::HashTableImpUtil ImpUtil; // First test - are the containers the same size? if (this->size() != other.size()) { return false; // RETURN } bslalg::BidirectionalLink *cursor = this->elementListRoot(); if (!cursor) { // containers are the same size, and empty. return true; // RETURN } while (cursor) { bslalg::BidirectionalLink *rhsFirst = ImpUtil::find<KEY_CONFIG>(other.d_anchor, ImpUtil::extractKey<KEY_CONFIG>(cursor), other.d_parameters.comparator(), other.d_parameters.hashCodeForKey( ImpUtil::extractKey<KEY_CONFIG>(cursor))); if (!rhsFirst) { return false; // no matching key // RETURN } bslalg::BidirectionalLink *endRange = this->findEndOfRange(cursor); bslalg::BidirectionalLink *rhsLast = other.findEndOfRange(rhsFirst); // Check the key-groups have the same length - a quick-fail test. bslalg::BidirectionalLink *endWalker = cursor->nextLink(); bslalg::BidirectionalLink *rhsWalker = rhsFirst->nextLink(); while (endWalker != endRange) { if (rhsWalker == rhsLast) { return false; // different length subsequences // RETURN } endWalker = endWalker->nextLink(); rhsWalker = rhsWalker->nextLink(); } if (rhsWalker != rhsLast) { return false; // different length subsequences // RETURN } // Efficiently compare identical prefixes: O[N] if sequences have the // same elements in the same order. Note that comparison of values in // nodes is tested using 'operator==' and not the key-equality // comparator stored in the hash table. while (cursor != endRange && (ImpUtil::extractValue<KEY_CONFIG>(cursor) == ImpUtil::extractValue<KEY_CONFIG>(rhsFirst))) { cursor = cursor->nextLink(); rhsFirst = rhsFirst->nextLink(); } if (cursor == endRange) { continue; } // Now comes the harder part of validating that one subsequence is a // permutation of another, by counting elements that compare equal // using the equality operator, 'operator=='. Note that this code // could be simplified for hash-tables with unique keys, as we can omit // the counting-scan, and merely test for any match within the 'other' // range. Trade off the ease of a single well-tested code path, vs. // the importance of an efficient 'operator==' for hash containers. // This is currently the only place the hash-table would care about // uniqueness, and risk different hash-table types for unique- vs. // multi-containers. Note again that comparison of values in nodes is // tested using 'operator==' and not the key-equality comparator stored // in the hash tables. for (bslalg::BidirectionalLink *marker = cursor; marker != endRange; marker = marker->nextLink()) { const ValueType& valueAtMarker = ImpUtil::extractValue<KEY_CONFIG>(marker); if (cursor != marker) { // skip on first pass only // Check if the value at 'marker' has already be seen. bslalg::BidirectionalLink *scanner = cursor; while (scanner != marker && ImpUtil::extractValue<KEY_CONFIG>(scanner) != valueAtMarker) { scanner = scanner->nextLink(); } if (scanner != marker) { // We have seen 'lhs' one before. continue; } } SizeType matches = 0; for (bslalg::BidirectionalLink *scanner = rhsFirst; scanner != rhsLast; scanner = scanner->nextLink()) { if (ImpUtil::extractValue<KEY_CONFIG>(scanner) == valueAtMarker) { ++matches; } } if (!matches) { return false; // RETURN } // Remember, *scanner is by definition a good match for (bslalg::BidirectionalLink *scanner = marker->nextLink(); scanner != endRange; scanner = scanner->nextLink()) { if (ImpUtil::extractValue<KEY_CONFIG>(scanner) == valueAtMarker) { if (!--matches) { // equal matches, but excluding initial return false; // RETURN } } } if (1 != matches) { return false; // RETURN } } cursor = endRange; } return true; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline const HASHER& HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::hasher() const { return d_parameters.originalHasher(); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline float HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::loadFactor() const { return static_cast<float>(static_cast<double>(this->size()) / static_cast<double>(this->numBuckets())); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline float HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::maxLoadFactor() const { return d_maxLoadFactor; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::maxNumBuckets() const { // This estimate is still on the high side, we should actually pick the // preceding entry from our table of prime numbers used for valid bucket // array sizes. There is no easy way to find that value at the moment // though. typedef typename AllocatorTraits:: template rebind_traits<bslalg::HashTableBucket> BucketAllocatorTraits; typedef typename BucketAllocatorTraits::allocator_type BucketAllocator; return BucketAllocatorTraits::max_size(BucketAllocator(this->allocator())); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::maxSize() const { return AllocatorTraits::max_size(this->allocator()) / sizeof(NodeType); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::numBuckets() const { return static_cast<SizeType>(d_anchor.bucketArraySize()); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::rehashThreshold() const { return d_capacity; } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline typename HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::SizeType HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>::size() const { return d_size; } } // close package namespace //----------------------------------------------------------------------------- // free functions and operators //----------------------------------------------------------------------------- template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline void bslstl::swap(bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& a, bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& b) { typedef bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR> TableType; if (::bsl::allocator_traits<ALLOCATOR>::propagate_on_container_swap::value || a.allocator() == b.allocator()) { a.swap(b); } else { // C++11 behavior: undefined for unequal allocators // BSLS_ASSERT(allocator() == other.allocator()); TableType aCopy(a, b.allocator()); TableType bCopy(b, a.allocator()); b.swap(aCopy); a.swap(bCopy); } } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline bool bslstl::operator==( const bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& lhs, const bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& rhs) { return lhs.hasSameValue(rhs); } template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> inline bool bslstl::operator!=( const bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& a, const bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR>& b) { return !(a == b); } template <class FUNCTOR> inline void bslstl::swap(bslstl::HashTable_HashWrapper<FUNCTOR> &a, bslstl::HashTable_HashWrapper<FUNCTOR> &b) { a.swap(b); } template <class FUNCTOR> inline void bslstl::swap(bslstl::HashTable_ComparatorWrapper<FUNCTOR> &a, bslstl::HashTable_ComparatorWrapper<FUNCTOR> &b) { a.swap(b); } // ============================================================================ // TYPE TRAITS // ============================================================================ // Type traits for HashTable: //: o A HashTable is bitwise movable if the both functors and the allocator are //: bitwise movable. //: o A HashTable uses 'bslma' allocators if the parameterized 'ALLOCATOR' is //: convertible from 'bslma::Allocator*'. namespace bslma { template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> struct UsesBslmaAllocator<bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR> > : bsl::is_convertible<Allocator*, ALLOCATOR>::type { }; template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> struct UsesBslmaAllocator<bslstl::HashTable_ImplParameters<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR> > : bsl::is_convertible<Allocator*, ALLOCATOR>::type { }; } // close namespace bslma namespace bslmf { template <class KEY_CONFIG, class HASHER, class COMPARATOR, class ALLOCATOR> struct IsBitwiseMoveable<bslstl::HashTable<KEY_CONFIG, HASHER, COMPARATOR, ALLOCATOR> > : bsl::integral_constant< bool, bslmf::IsBitwiseMoveable<HASHER>::value && bslmf::IsBitwiseMoveable<COMPARATOR>::value && bslmf::IsBitwiseMoveable<ALLOCATOR>::value> {}; } // close namespace bslmf } // close enterprise namespace #else // if ! defined(DEFINED_BSLSTL_HASHTABLE_H) # error Not valid except when included from bslstl_hashtable.h #endif // ! defined(COMPILING_BSLSTL_HASHTABLE_H) #endif // ! defined(INCLUDED_BSLSTL_HASHTABLE_CPP03) // ---------------------------------------------------------------------------- // Copyright 2022 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------