diff --git a/groups/bsl/bslstl/bslstl_hashtable.h b/groups/bsl/bslstl/bslstl_hashtable.h index ff44c1782c..64a0b3e6bf 100644 --- a/groups/bsl/bslstl/bslstl_hashtable.h +++ b/groups/bsl/bslstl/bslstl_hashtable.h @@ -2552,6 +2552,33 @@ class HashTable { /// having the specified `key`. SizeType bucketIndexForKey(const KeyType& key) const; + /// Return the index of the bucket that would contain all the elements + /// equivalent to the specified `key`. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + SizeType>::type + bucketIndexForKey(const LOOKUP_KEY& key) const + { + typedef typename + HashTable::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( + bslalg::HashTableImpUtil::computeBucketIndex( + hashCode, + d_anchor.bucketArraySize())); + } + /// Return a reference providing non-modifiable access to the /// key-equality comparison functor used by this hash table. const COMPARATOR& comparator() const; diff --git a/groups/bsl/bslstl/bslstl_hashtable_cpp03.h b/groups/bsl/bslstl/bslstl_hashtable_cpp03.h index 3a20eacd23..cf3a06382a 100644 --- a/groups/bsl/bslstl/bslstl_hashtable_cpp03.h +++ b/groups/bsl/bslstl/bslstl_hashtable_cpp03.h @@ -21,7 +21,7 @@ // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // -// Generated on Sun Sep 1 05:39:09 2024 +// Generated on Tue Nov 5 07:45:21 2024 // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifdef COMPILING_BSLSTL_HASHTABLE_H @@ -2822,6 +2822,33 @@ class HashTable { /// having the specified `key`. SizeType bucketIndexForKey(const KeyType& key) const; + /// Return the index of the bucket that would contain all the elements + /// equivalent to the specified `key`. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + SizeType>::type + bucketIndexForKey(const LOOKUP_KEY& key) const + { + typedef typename + HashTable::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( + bslalg::HashTableImpUtil::computeBucketIndex( + hashCode, + d_anchor.bucketArraySize())); + } + /// Return a reference providing non-modifiable access to the /// key-equality comparison functor used by this hash table. const COMPARATOR& comparator() const; diff --git a/groups/bsl/bslstl/bslstl_unorderedmap.h b/groups/bsl/bslstl/bslstl_unorderedmap.h index d191398e68..b8ea0a7088 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmap.h +++ b/groups/bsl/bslstl/bslstl_unorderedmap.h @@ -1963,6 +1963,21 @@ class unordered_map { /// specified `key` would be inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets maintained + /// by this unordered map, where values having a key equivalent to the + /// specified `key` would be inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return the number of buckets in the array of buckets maintained by /// this unordered map. size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT; diff --git a/groups/bsl/bslstl/bslstl_unorderedmap_cpp03.h b/groups/bsl/bslstl/bslstl_unorderedmap_cpp03.h index 9e96d3acdf..a833b949d7 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmap_cpp03.h +++ b/groups/bsl/bslstl/bslstl_unorderedmap_cpp03.h @@ -21,7 +21,7 @@ // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // -// Generated on Sun Sep 1 18:48:19 2024 +// Generated on Tue Nov 5 08:09:52 2024 // Command line: sim_cpp11_features.pl bslstl_unorderedmap.h #ifdef COMPILING_BSLSTL_UNORDEREDMAP_H @@ -2661,6 +2661,21 @@ class unordered_map { /// specified `key` would be inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets maintained + /// by this unordered map, where values having a key equivalent to the + /// specified `key` would be inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return the number of buckets in the array of buckets maintained by /// this unordered map. size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT; diff --git a/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp b/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp index 046b10b5ac..ef0c632d99 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp @@ -1584,8 +1584,9 @@ void testTransparentComparator(Container& container, bool isTransparent, int initKeyValue) { - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename Container::const_local_iterator LocalIterator; + typedef typename Container::const_iterator Iterator; + typedef typename Container::size_type Count; int expectedConversionCount = 0; @@ -1660,6 +1661,43 @@ void testTransparentComparator(Container& container, container.equal_range(nonExistingKey); ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + + // Testing `bucket`. + const Count bucketFound = container.bucket(existingKey); + const Count bucketNotFound = container.bucket(nonExistingKey); + + if (!isTransparent) { + ++expectedConversionCount; + } + + ASSERTV(expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); + + // check that we found the right bucket + bool found_it; + const typename Container::key_equal c_eq = container.key_eq(); + + found_it = false; + for (LocalIterator it = container.begin(bucketFound); + it != container.end(bucketFound); + ++it) { + if (c_eq(it->first, existingKey)) { + found_it = true; + } + } + ASSERT(found_it); + + found_it = false; + for (LocalIterator it = container.begin(bucketNotFound); + it != container.end(bucketNotFound); + ++it) { + if (c_eq(it->first, nonExistingKey)) { + found_it = true; + } + } + ASSERT(!found_it); } // ================ @@ -9794,6 +9832,7 @@ int main(int argc, char *argv[]) // CONCERN: `find` properly handles transparent comparators. // CONCERN: `count` properly handles transparent comparators. // CONCERN: `equal_range` properly handles transparent comparators. + // CONCERN: `bucket` properly handles transparent comparators. // -------------------------------------------------------------------- if (verbose) printf("\n" "TESTING TRANSPARENT COMPARATOR" "\n" diff --git a/groups/bsl/bslstl/bslstl_unorderedmultimap.h b/groups/bsl/bslstl/bslstl_unorderedmultimap.h index 80d9e5ed75..11bd5f5952 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmultimap.h +++ b/groups/bsl/bslstl/bslstl_unorderedmultimap.h @@ -1475,6 +1475,21 @@ class unordered_multimap { /// `key` would be inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets maintained + /// by this unordered map, where values having a key equivalent to the + /// specified `key` would be inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return the number of buckets in the array of buckets maintained by /// this unordered multimap. size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT; diff --git a/groups/bsl/bslstl/bslstl_unorderedmultimap_cpp03.h b/groups/bsl/bslstl/bslstl_unorderedmultimap_cpp03.h index 04364dd343..82c10f74de 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmultimap_cpp03.h +++ b/groups/bsl/bslstl/bslstl_unorderedmultimap_cpp03.h @@ -21,7 +21,7 @@ // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // -// Generated on Mon Oct 14 10:32:16 2024 +// Generated on Thu Nov 7 07:41:40 2024 // Command line: sim_cpp11_features.pl bslstl_unorderedmultimap.h #ifdef COMPILING_BSLSTL_UNORDEREDMULTIMAP_H @@ -898,6 +898,21 @@ class unordered_multimap { /// `key` would be inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets maintained + /// by this unordered map, where values having a key equivalent to the + /// specified `key` would be inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return the number of buckets in the array of buckets maintained by /// this unordered multimap. size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT; diff --git a/groups/bsl/bslstl/bslstl_unorderedmultimap_test.t.cpp b/groups/bsl/bslstl/bslstl_unorderedmultimap_test.t.cpp index 9895b3a8d2..3334c791e7 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmultimap_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedmultimap_test.t.cpp @@ -1361,8 +1361,9 @@ void testTransparentComparator(Container& container, bool isTransparent, int initKeyValue) { - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename Container::const_local_iterator LocalIterator; + typedef typename Container::const_iterator Iterator; + typedef typename Container::size_type Count; int expectedConversionCount = 0; @@ -1437,6 +1438,43 @@ void testTransparentComparator(Container& container, container.equal_range(nonExistingKey); ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + + // Testing `bucket`. + const Count bucketFound = container.bucket(existingKey); + const Count bucketNotFound = container.bucket(nonExistingKey); + + if (!isTransparent) { + ++expectedConversionCount; + } + + ASSERTV(expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); + + // check that we found the right bucket + bool found_it; + const typename Container::key_equal c_eq = container.key_eq(); + + found_it = false; + for (LocalIterator it = container.begin(bucketFound); + it != container.end(bucketFound); + ++it) { + if (c_eq(it->first, existingKey)) { + found_it = true; + } + } + ASSERT(found_it); + + found_it = false; + for (LocalIterator it = container.begin(bucketNotFound); + it != container.end(bucketNotFound); + ++it) { + if (c_eq(it->first, nonExistingKey)) { + found_it = true; + } + } + ASSERT(!found_it); } } // close unnamed namespace diff --git a/groups/bsl/bslstl/bslstl_unorderedmultiset.h b/groups/bsl/bslstl/bslstl_unorderedmultiset.h index b4e555c235..83e2cdee52 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmultiset.h +++ b/groups/bsl/bslstl/bslstl_unorderedmultiset.h @@ -1489,6 +1489,21 @@ class unordered_multiset /// inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets of this + /// container, where a value equivalent to the specified `key` would be + /// inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return the number of buckets in the array of buckets maintained by /// this unordered multiset. size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT; diff --git a/groups/bsl/bslstl/bslstl_unorderedmultiset_cpp03.h b/groups/bsl/bslstl/bslstl_unorderedmultiset_cpp03.h index 27ee388d12..90d437eeee 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmultiset_cpp03.h +++ b/groups/bsl/bslstl/bslstl_unorderedmultiset_cpp03.h @@ -21,7 +21,7 @@ // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // -// Generated on Sun Sep 1 18:48:19 2024 +// Generated on Thu Nov 7 07:41:40 2024 // Command line: sim_cpp11_features.pl bslstl_unorderedmultiset.h #ifdef COMPILING_BSLSTL_UNORDEREDMULTISET_H @@ -1111,6 +1111,21 @@ class unordered_multiset /// inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets of this + /// container, where a value equivalent to the specified `key` would be + /// inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return the number of buckets in the array of buckets maintained by /// this unordered multiset. size_type bucket_count() const BSLS_KEYWORD_NOEXCEPT; diff --git a/groups/bsl/bslstl/bslstl_unorderedmultiset_test.t.cpp b/groups/bsl/bslstl/bslstl_unorderedmultiset_test.t.cpp index eee04e7e47..eb90cc437d 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmultiset_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedmultiset_test.t.cpp @@ -1570,8 +1570,9 @@ void testTransparentComparator(Container& container, bool isTransparent, int initKeyValue) { - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename Container::const_local_iterator LocalIterator; + typedef typename Container::const_iterator Iterator; + typedef typename Container::size_type Count; int expectedConversionCount = 0; @@ -1646,6 +1647,43 @@ void testTransparentComparator(Container& container, container.equal_range(nonExistingKey); ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + + // Testing `bucket`. + const Count bucketFound = container.bucket(existingKey); + const Count bucketNotFound = container.bucket(nonExistingKey); + + if (!isTransparent) { + ++expectedConversionCount; + } + + ASSERTV(expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); + + // check that we found the right bucket + bool found_it; + const typename Container::key_equal c_eq = container.key_eq(); + + found_it = false; + for (LocalIterator it = container.begin(bucketFound); + it != container.end(bucketFound); + ++it) { + if (c_eq(*it, existingKey)) { + found_it = true; + } + } + ASSERT(found_it); + + found_it = false; + for (LocalIterator it = container.begin(bucketNotFound); + it != container.end(bucketNotFound); + ++it) { + if (c_eq(*it, nonExistingKey)) { + found_it = true; + } + } + ASSERT(!found_it); } } // close unnamed namespace diff --git a/groups/bsl/bslstl/bslstl_unorderedset.h b/groups/bsl/bslstl/bslstl_unorderedset.h index 1e71b534d3..cf26a00179 100644 --- a/groups/bsl/bslstl/bslstl_unorderedset.h +++ b/groups/bsl/bslstl/bslstl_unorderedset.h @@ -1407,6 +1407,21 @@ class unordered_set { /// inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets of this + /// container, where a value equivalent to the specified `key` would be + /// inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return a local iterator providing non-modifiable access to the first /// `value_type` object (in the sequence of `value_type` objects) of the /// bucket having the specified `index` in the array of buckets diff --git a/groups/bsl/bslstl/bslstl_unorderedset_cpp03.h b/groups/bsl/bslstl/bslstl_unorderedset_cpp03.h index f7af84b0f7..d3808a4bf5 100644 --- a/groups/bsl/bslstl/bslstl_unorderedset_cpp03.h +++ b/groups/bsl/bslstl/bslstl_unorderedset_cpp03.h @@ -21,7 +21,7 @@ // regions of C++11 code, then this header contains no code and is not // '#include'd in the original header. // -// Generated on Sun Sep 1 18:48:19 2024 +// Generated on Thu Nov 7 07:41:40 2024 // Command line: sim_cpp11_features.pl bslstl_unorderedset.h #ifdef COMPILING_BSLSTL_UNORDEREDSET_H @@ -1105,6 +1105,21 @@ class unordered_set { /// inserted. size_type bucket(const key_type& key) const; + /// Return the index of the bucket, in the array of buckets of this + /// container, where a value equivalent to the specified `key` would be + /// inserted. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + size_type>::type + bucket(const LOOKUP_KEY& key) const + { + return d_impl.bucketIndexForKey(key); + } + /// Return a local iterator providing non-modifiable access to the first /// `value_type` object (in the sequence of `value_type` objects) of the /// bucket having the specified `index` in the array of buckets diff --git a/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp b/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp index c171e06f57..b3c535b6cd 100644 --- a/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp @@ -1575,8 +1575,9 @@ void testTransparentComparator(Container& container, bool isTransparent, int initKeyValue) { - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename Container::const_local_iterator LocalIterator; + typedef typename Container::const_iterator Iterator; + typedef typename Container::size_type Count; int expectedConversionCount = 0; @@ -1651,6 +1652,43 @@ void testTransparentComparator(Container& container, container.equal_range(nonExistingKey); ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + + // Testing `bucket`. + const Count bucketFound = container.bucket(existingKey); + const Count bucketNotFound = container.bucket(nonExistingKey); + + if (!isTransparent) { + ++expectedConversionCount; + } + + ASSERTV(expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); + + // check that we found the right bucket + bool found_it; + const typename Container::key_equal c_eq = container.key_eq(); + + found_it = false; + for (LocalIterator it = container.begin(bucketFound); + it != container.end(bucketFound); + ++it) { + if (c_eq(*it, existingKey)) { + found_it = true; + } + } + ASSERT(found_it); + + found_it = false; + for (LocalIterator it = container.begin(bucketNotFound); + it != container.end(bucketNotFound); + ++it) { + if (c_eq(*it, nonExistingKey)) { + found_it = true; + } + } + ASSERT(!found_it); } } // close unnamed namespace