diff --git a/groups/bsl/bslstl/bslstl_hashtable.h b/groups/bsl/bslstl/bslstl_hashtable.h index c2a7e1d422..dbf916f658 100644 --- a/groups/bsl/bslstl/bslstl_hashtable.h +++ b/groups/bsl/bslstl/bslstl_hashtable.h @@ -1483,7 +1483,7 @@ BSLS_IDENT("$Id: $") #if BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES // Include version that can be compiled with C++03 -// Generated on Thu Oct 21 10:11:37 2021 +// Generated on Thu Nov 21 09:50:52 2024 // Command line: sim_cpp11_features.pl bslstl_hashtable.h # define COMPILING_BSLSTL_HASHTABLE_H # include @@ -2286,6 +2286,68 @@ class HashTable { bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value); +#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES + /// 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`. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , bslalg::BidirectionalLink *>::type + insertIfMissingTransparent( + bool *isInsertedFlag, + BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) value) + { + BSLS_ASSERT(isInsertedFlag); + + const LOOKUP_KEY& lvalue = value; + + size_t hashCode = this->d_parameters.hashCodeForTransparentKey(lvalue); + + bslalg::BidirectionalLink *position = + bslalg::HashTableImpUtil::findTransparent( + d_anchor, + lvalue, + d_parameters.comparator(), + hashCode); + + *isInsertedFlag = (!position); + + if(!position) { + if (d_size >= d_capacity) { + this->rehashForNumBuckets(numBuckets() * 2); + } + + position = d_parameters.nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + bslalg::HashTableImpUtil::insertAtFrontOfBucket(&d_anchor, + position, + hashCode); + ++d_size; + } + + return position; + } +#endif + /// 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 @@ -2346,6 +2408,68 @@ class HashTable { bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BDE_OTHER_TYPE&& obj); + + /// If a key equivalent to the specified `key` already exists in this + /// hash-table, assign the specified `obj` to the value associated with + /// that key, load `false` into the specified `isInsertedFlag` and + /// return a pointer to the existing entry. Otherwise, insert into this + /// hash-table a newly-created `value_type` object, constructed from + /// `key` and `obj`, load `true` into `isInsertedFlag`, and return a + /// pointer to the newly-created entry. Use the optionally specified + /// `hint` as a starting place for the search for the existing key. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , bslalg::BidirectionalLink *>::type + insertOrAssignTransparent(bool *isInsertedFlag, + bslalg::BidirectionalLink *hint, + LOOKUP_KEY&& key, + BDE_OTHER_TYPE&& obj) + { + typedef bslalg::HashTableImpUtil ImpUtil; + + size_t hashCode = this->d_parameters.hashCodeForTransparentKey(key); + // Use the hint, if we can + if (!hint + || !d_parameters.comparator()(key, + ImpUtil::extractKey(hint))) { + hint = bslalg::HashTableImpUtil::findTransparent( + d_anchor, + key, + d_parameters.comparator(), + hashCode); + } + + if (hint) { // assign + static_cast(hint)->value().second = + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj); + *isInsertedFlag = false; + return hint; // RETURN + } + + // insert + if (d_size >= d_capacity) { + this->rehashForNumBuckets(numBuckets() * 2); + } + + // Make a new node + hint = d_parameters.nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + + // Add it to the hash table + HashTable_NodeProctor + nodeProctor(&d_parameters.nodeFactory(), hint); + ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); + nodeProctor.release(); + ++d_size; + + *isInsertedFlag = true; + return hint; + } #endif /// Re-organize this hash-table to have at least the specified @@ -2471,21 +2595,18 @@ class HashTable { { typedef bslalg::HashTableImpUtil ImpUtil; - const LOOKUP_KEY& lvalue = key; -// const std::size_t hashCode = -// this->d_parameters.hashCodeForTransparentKey(lvalue); const std::size_t hashCode = - this->d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); // Use the hint, if we can if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2557,6 +2678,8 @@ class HashTable { /// Return the index of the bucket that would contain all the elements /// equivalent to the specified `key`. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -2577,7 +2700,7 @@ class HashTable { size_t hashCode = this->d_parameters.hashCodeForKey(key); return static_cast( - bslalg::HashTableImpUtil::computeBucketIndex( + bslalg::HashTableImpUtil::computeBucketIndex( hashCode, d_anchor.bucketArraySize())); } @@ -2602,6 +2725,8 @@ class HashTable { /// 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. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -5237,7 +5362,7 @@ struct IsBitwiseMoveable -void testSetTransparentComparator(Container& container, - bool isTransparent, - int initKeyValue) +template +void testSetTransparentComparator(t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { typedef typename bslalg::BidirectionalLink *Link; - typedef typename Container::SizeType Count; - typedef typename Container::ValueType Value; + typedef typename t_CONTAINER::SizeType Count; + typedef typename t_CONTAINER::ValueType Value; const int expectedConversionCount = isTransparent ? 0 : 1; @@ -3821,11 +3822,15 @@ void testSetTransparentComparator(Container& container, ASSERT(NULL != EXISTING_F); ASSERT(existingKey.value() == static_cast *>(EXISTING_F)->value()); - ASSERT(existingKey.conversionCount() == expectedConversionCount); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); const Link NON_EXISTING_F = container.find(nonExistingKey); ASSERT(NULL == NON_EXISTING_F); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } { @@ -3836,17 +3841,21 @@ void testSetTransparentComparator(Container& container, Link first, last; container.findRange(&first, &last, existingKey); - - ASSERT(expectedConversionCount == existingKey.conversionCount()); ASSERT(first != last); for (Link it = first; it != last; it = it->nextLink()) { ASSERT(existingKey.value() == static_cast *>(it)->value()); } + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + container.findRange(&first, &last, nonExistingKey); ASSERT(first == last); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } @@ -3855,13 +3864,17 @@ void testSetTransparentComparator(Container& container, existingKey.resetConversionCount(); nonExistingKey.resetConversionCount(); - const Count bucketFound = container.bucketIndexForKey(existingKey); - const Count bucketNotFound = container.bucketIndexForKey(nonExistingKey); + const Count bucketFound = container.bucketIndexForKey(existingKey); + (void) bucketFound; + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, existingKey.conversionCount(), - expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), - expectedConversionCount == nonExistingKey.conversionCount()); + const Count bucketNotFound = container.bucketIndexForKey(nonExistingKey); + (void) bucketNotFound; + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } } @@ -3871,14 +3884,14 @@ void testSetTransparentComparator(Container& container, /// `const`-qualified type, we are using the "reference" here as a sort of /// universal reference; conceptually, the object remains constant, but we /// want to test `const`-qualified and non-`const`-qualified overloads. -template -void testMapTransparentComparator(Container& container, - bool isTransparent, - int initKeyValue) +template +void testMapTransparentComparator(t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { typedef typename bslalg::BidirectionalLink *Link; - typedef typename Container::SizeType Count; - typedef typename Container::ValueType Value; + typedef typename t_CONTAINER::SizeType Count; + typedef typename t_CONTAINER::ValueType Value; const int expectedConversionCount = isTransparent ? 0 : 1; @@ -3897,11 +3910,15 @@ void testMapTransparentComparator(Container& container, ASSERT(existingKey.value() == static_cast *> (EXISTING_F)->value().first); - ASSERT(existingKey.conversionCount() == expectedConversionCount); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); const Link NON_EXISTING_F = container.find(nonExistingKey); ASSERT(NULL == NON_EXISTING_F); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } { @@ -3913,7 +3930,9 @@ void testMapTransparentComparator(Container& container, container.findRange(&first, &last, existingKey); - ASSERT(expectedConversionCount == existingKey.conversionCount()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); ASSERT(first != last); for (Link it = first; it != last; it = it->nextLink()) { ASSERT(existingKey.value() == @@ -3923,22 +3942,27 @@ void testMapTransparentComparator(Container& container, container.findRange(&first, &last, nonExistingKey); ASSERT(first == last); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - { // Testing `bucketIndexForKey`. existingKey.resetConversionCount(); nonExistingKey.resetConversionCount(); - const Count bucketFound = container.bucketIndexForKey(existingKey); - const Count bucketNotFound = container.bucketIndexForKey(nonExistingKey); + const Count bucketFound = container.bucketIndexForKey(existingKey); + (void) bucketFound; + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, existingKey.conversionCount(), - expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), - expectedConversionCount == nonExistingKey.conversionCount()); + const Count bucketNotFound = container.bucketIndexForKey(nonExistingKey); + (void) bucketNotFound; + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } } @@ -3946,28 +3970,74 @@ void testMapTransparentComparator(Container& container, /// specified `container`, and count the number of conversions expected /// based on the specified `isTransparent`. Since these tests can modify /// the container, we make a copy of it for each test. -template -void testSetTransparentComparatorMutable(const Container& container, - bool isTransparent, - int initKeyValue) +template +void testSetTransparentComparatorMutable(const t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { - // No transparent modifying operations on sets. + typedef typename bslalg::BidirectionalLink *Link; + typedef typename t_CONTAINER::SizeType Count; + typedef typename t_CONTAINER::ValueType Value; + + const int expectedConversionCount = isTransparent ? 0 : 1; + const Count size = container.size(); + + TransparentlyComparable existingKey(initKeyValue); + TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue + : -100); + + { + // Testing `insertIfMissingTransparent`. Note that this is only + // available when isTransparent is true; but we match the structure of + // the other test routines to make reading easier. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + bool wasInserted; + Link link; + + // with an existing key + link = c.insertIfMissingTransparent(&wasInserted, existingKey); + ASSERT(!wasInserted); + ASSERT(size == c.size()); + ASSERT(existingKey.value() == + static_cast *>(link)->value()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + link = c.insertIfMissingTransparent(&wasInserted, nonExistingKey); + ASSERT( wasInserted); + ASSERT(size + 1 == c.size()); + ASSERT(nonExistingKey.value() == + static_cast *>(link)->value()); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } } /// Search for a value equal to the specified `initKeyValue` in the /// specified `container`, and count the number of conversions expected /// based on the specified `isTransparent`. Since these tests can modify /// the container, we make a copy of it for each test. -template -void testMapTransparentComparatorMutable(const Container& container, - bool isTransparent, - int initKeyValue) +template +void testMapTransparentComparatorMutable(const t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { -// bslalg::BidirectionalLink *>::type tryEmplace( typedef typename bslalg::BidirectionalLink *Link; - typedef typename Container::SizeType Count; - typedef typename Container::ValueType Value; + typedef typename t_CONTAINER::SizeType Count; + typedef typename t_CONTAINER::ValueType Value; const int expectedConversionCount = isTransparent ? 0 : 1; const Count size = container.size(); @@ -3981,7 +4051,7 @@ void testMapTransparentComparatorMutable(const Container& container, existingKey.resetConversionCount(); nonExistingKey.resetConversionCount(); - Container c(container); + t_CONTAINER c(container); bool wasInserted; Link link; @@ -4007,7 +4077,9 @@ void testMapTransparentComparatorMutable(const Container& container, ASSERT(size + 1 == c.size()); ASSERT(nonExistingKey.value() == static_cast *>(link)->value().first); - ASSERT(1 == nonExistingKey.conversionCount()); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); } } @@ -9752,7 +9824,6 @@ int main(int argc, char *argv[]) printf("\tTesting mutable non-transparent map.\n"); } testSetTransparentComparator (mSet, false, KEY); - testSetTransparentComparatorMutable(mSet, false, KEY); if (veryVerbose) { printf("\tTesting const transparent map.\n"); diff --git a/groups/bsl/bslstl/bslstl_hashtable_cpp03.h b/groups/bsl/bslstl/bslstl_hashtable_cpp03.h index a5c3b8caee..acde7f4e4c 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 Mon Nov 25 22:33:57 2024 +// Generated on Wed Dec 11 11:35:48 2024 // Command line: sim_cpp11_features.pl bslstl_hashtable.h #ifdef COMPILING_BSLSTL_HASHTABLE_H @@ -1258,6 +1258,50 @@ class HashTable { bool *isInsertedFlag, BSLS_COMPILERFEATURES_FORWARD_REF(SOURCE_TYPE) value); +// {{{ BEGIN GENERATED CODE +// The generated code below is a workaround for the absence of perfect +// forwarding in some compilers. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , bslalg::BidirectionalLink *>::type + insertIfMissingTransparent( + bool *isInsertedFlag, + BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) value) + { + BSLS_ASSERT(isInsertedFlag); + + const LOOKUP_KEY& lvalue = value; + + size_t hashCode = this->d_parameters.hashCodeForTransparentKey(lvalue); + + bslalg::BidirectionalLink *position = + bslalg::HashTableImpUtil::findTransparent( + d_anchor, + lvalue, + d_parameters.comparator(), + hashCode); + + *isInsertedFlag = (!position); + + if(!position) { + if (d_size >= d_capacity) { + this->rehashForNumBuckets(numBuckets() * 2); + } + + position = d_parameters.nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + bslalg::HashTableImpUtil::insertAtFrontOfBucket(&d_anchor, + position, + hashCode); + ++d_size; + } + + return position; + } +// }}} END GENERATED CODE + /// 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 @@ -1312,6 +1356,54 @@ class HashTable { bslalg::BidirectionalLink *hint, BSLS_COMPILERFEATURES_FORWARD_REF(KEY_ARG) key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); + + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , bslalg::BidirectionalLink *>::type + insertOrAssignTransparent(bool *isInsertedFlag, + bslalg::BidirectionalLink *hint, + BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) key, + BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj) + { + typedef bslalg::HashTableImpUtil ImpUtil; + + size_t hashCode = this->d_parameters.hashCodeForTransparentKey(key); + if (!hint + || !d_parameters.comparator()(key, + ImpUtil::extractKey(hint))) { + hint = bslalg::HashTableImpUtil::findTransparent( + d_anchor, + key, + d_parameters.comparator(), + hashCode); + } + + if (hint) { + static_cast(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(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + + HashTable_NodeProctor + nodeProctor(&d_parameters.nodeFactory(), hint); + ImpUtil::insertAtFrontOfBucket(&d_anchor, hint, hashCode); + nodeProctor.release(); + ++d_size; + + *isInsertedFlag = true; + return hint; + } // }}} END GENERATED CODE /// Re-organize this hash-table to have at least the specified @@ -1389,26 +1481,26 @@ class HashTable { #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 +#ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_D +#define BSLSTL_HASHTABLE_VARIADIC_LIMIT_D BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, const KeyType& key); -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 template bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, const KeyType& key, BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01); -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 template bslalg::BidirectionalLink *tryEmplace( @@ -1417,9 +1509,9 @@ class HashTable { const KeyType& key, BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02); -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 template @@ -1430,9 +1522,9 @@ class HashTable { 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 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 template = 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 template = 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 template = 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 template = 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 template = 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 template = 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 template = 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, bslmf::MovableRef key); -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 template bslalg::BidirectionalLink *tryEmplace( bool *isInsertedFlag, bslalg::BidirectionalLink *hint, bslmf::MovableRef key, BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01); -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 template bslalg::BidirectionalLink *tryEmplace( @@ -1605,9 +1697,9 @@ class HashTable { bslmf::MovableRef key, BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_01) args_01, BSLS_COMPILERFEATURES_FORWARD_REF(ARGS_02) args_02); -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 template @@ -1618,9 +1710,9 @@ class HashTable { 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 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 template = 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 template = 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 template = 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 template = 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 template = 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 template = 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 template = 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 template typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1781,18 +1873,17 @@ class HashTable { { typedef bslalg::HashTableImpUtil ImpUtil; - const LOOKUP_KEY& lvalue = key; const std::size_t hashCode = - this->d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -1835,9 +1926,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 template typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1850,18 +1941,17 @@ class HashTable { { typedef bslalg::HashTableImpUtil ImpUtil; - const LOOKUP_KEY& lvalue = key; const std::size_t hashCode = - this->d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -1906,9 +1996,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 template typename bsl::enable_if< @@ -1923,18 +2013,17 @@ class HashTable { { typedef bslalg::HashTableImpUtil ImpUtil; - const LOOKUP_KEY& lvalue = key; const std::size_t hashCode = - this->d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -1981,9 +2070,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 template @@ -2000,18 +2089,17 @@ class HashTable { { typedef bslalg::HashTableImpUtil ImpUtil; - const LOOKUP_KEY& lvalue = key; const std::size_t hashCode = - this->d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2060,9 +2148,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 3 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2143,9 +2230,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2230,9 +2316,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2321,9 +2406,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2416,9 +2500,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2515,9 +2598,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2618,9 +2700,9 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 template d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2725,7 +2806,7 @@ class HashTable { *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_C >= 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 #else // The generated code below is a workaround for the absence of perfect @@ -2757,18 +2838,17 @@ class HashTable { { typedef bslalg::HashTableImpUtil ImpUtil; - const LOOKUP_KEY& lvalue = key; const std::size_t hashCode = - this->d_parameters.hashCodeForKey(lvalue); + this->d_parameters.hashCodeForTransparentKey(key); if (!hint || !d_parameters.comparator()( - lvalue, + key, ImpUtil::extractKey(hint))) { hint = bslalg::HashTableImpUtil::findTransparent( d_anchor, - lvalue, + key, d_parameters.comparator(), hashCode); } @@ -2836,6 +2916,8 @@ class HashTable { /// Return the index of the bucket that would contain all the elements /// equivalent to the specified `key`. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -2856,7 +2938,7 @@ class HashTable { size_t hashCode = this->d_parameters.hashCodeForKey(key); return static_cast( - bslalg::HashTableImpUtil::computeBucketIndex( + bslalg::HashTableImpUtil::computeBucketIndex( hashCode, d_anchor.bucketArraySize())); } @@ -2881,6 +2963,8 @@ class HashTable { /// 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. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename bsl::enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -4471,10 +4555,10 @@ HashTable::operator=( #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 +#ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_E +#define BSLSTL_HASHTABLE_VARIADIC_LIMIT_E BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 0 template bslalg::BidirectionalLink * HashTable::emplace( @@ -4515,9 +4599,9 @@ HashTable::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 1 template template bslalg::BidirectionalLink * @@ -4559,9 +4643,9 @@ HashTable::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 2 template template @@ -4606,9 +4690,9 @@ HashTable::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 3 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 4 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 5 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 6 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 7 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 8 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 9 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 10 template template ::emplace( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 10 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 0 template bslalg::BidirectionalLink * HashTable::emplaceWithHint( @@ -5136,9 +5220,9 @@ HashTable::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 1 template template bslalg::BidirectionalLink * @@ -5183,9 +5267,9 @@ HashTable::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 2 template template @@ -5233,9 +5317,9 @@ HashTable::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 3 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 4 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 5 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 6 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 7 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 8 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 9 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 10 template template ::emplaceWithHint( return newNode; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 10 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 0 template bslalg::BidirectionalLink * HashTable::emplaceIfMissing( @@ -5791,9 +5875,9 @@ HashTable::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 1 template template bslalg::BidirectionalLink * @@ -5842,9 +5926,9 @@ HashTable::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 2 template template @@ -5896,9 +5980,9 @@ HashTable::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 3 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 3 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 4 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 5 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 6 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 7 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 8 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 9 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 10 template template ::emplaceIfMissing( return position; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_D >= 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_E >= 10 #else // The generated code below is a workaround for the absence of perfect @@ -6884,10 +6968,10 @@ HashTable::swap(HashTable& other) #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 +#ifndef BSLSTL_HASHTABLE_VARIADIC_LIMIT_G +#define BSLSTL_HASHTABLE_VARIADIC_LIMIT_G BSLSTL_HASHTABLE_VARIADIC_LIMIT #endif -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 0 template inline bslalg::BidirectionalLink * @@ -6944,9 +7028,9 @@ HashTable::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 1 template template inline @@ -7008,9 +7092,9 @@ HashTable::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 2 template template @@ -7077,9 +7161,9 @@ HashTable::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 3 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 3 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 4 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 5 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 6 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 7 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 8 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 9 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 10 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 10 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 0 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 0 template inline bslalg::BidirectionalLink * @@ -7872,9 +7956,9 @@ HashTable::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 0 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 0 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 1 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 1 template template inline @@ -7938,9 +8022,9 @@ HashTable::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 1 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 1 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 2 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 2 template template @@ -8010,9 +8094,9 @@ HashTable::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 2 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 2 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 3 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 3 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 3 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 3 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 4 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 4 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 4 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 4 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 5 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 5 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 5 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 5 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 6 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 6 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 6 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 6 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 7 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 7 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 7 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 7 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 8 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 8 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 8 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 8 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 9 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 9 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 9 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 9 -#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 10 +#if BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 10 template template ::tryEmplace( *isInsertedFlag = true; return hint; } -#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_F >= 10 +#endif // BSLSTL_HASHTABLE_VARIADIC_LIMIT_G >= 10 #else // The generated code below is a workaround for the absence of perfect diff --git a/groups/bsl/bslstl/bslstl_map.h b/groups/bsl/bslstl/bslstl_map.h index b205129800..7ece30c02a 100644 --- a/groups/bsl/bslstl/bslstl_map.h +++ b/groups/bsl/bslstl/bslstl_map.h @@ -1259,6 +1259,11 @@ class map { pair insert_or_assign(const KEY& key, BDE_OTHER_TYPE&& obj); + template + pair insert_or_assign( + BloombergLP::bslmf::MovableRef key, + BDE_OTHER_TYPE&& obj); + /// If a key equivalent to the specified `key` already exists in this /// map, assign the specified `obj` to the value associated with that /// key, and return a pair containing an iterator referring to the @@ -1267,10 +1272,44 @@ class map { /// `(std::forward(key), std::forward(obj)...))`, /// and return a pair containing an iterator referring to the /// newly-created entry and `true`. - template - pair insert_or_assign( - BloombergLP::bslmf::MovableRef key, - BDE_OTHER_TYPE&& obj); + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value, + pair >::type + insert_or_assign(LOOKUP_KEY&& key, BDE_OTHER_TYPE&& obj) + { + typedef pair Result; + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + key); + + if (!comparisonResult) { // ASSIGN + iterator(insertLocation)->second = + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj); + return Result(iterator(insertLocation), false); // RETURN + } + + // INSERT + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + + return Result(iterator(node), true); + } /// If a key equivalent to the specified `key` already exists in this /// map, assign the specified `obj` to the value associated with that @@ -1298,6 +1337,57 @@ class map { iterator insert_or_assign(const_iterator hint, BloombergLP::bslmf::MovableRef key, BDE_OTHER_TYPE&& obj); + + + /// If a key equivalent to the specified `key` already exists in this + /// _map, assign the specified `obj` to the value associated with that + /// key, and return an iterator referring to the existing item. + /// Otherwise, insert into this map a newly-created `value_type` object + /// constructed from + /// `(std::forward(key), std::forward(obj)...))`, + /// and return an iterator referring to the newly-created entry. Use + /// the specified `hint` as a starting point for checking to see if the + /// key already in the map. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value, + iterator>::type + insert_or_assign(const_iterator hint, LOOKUP_KEY&& key, BDE_OTHER_TYPE&& obj) + { + BloombergLP::bslalg::RbTreeNode *hintNode = + const_cast(hint.node()); + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + key, + hintNode); + + if (!comparisonResult) { // ASSIGN + iterator(insertLocation)->second = + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj); + return iterator(insertLocation); // RETURN + } + + // INSERT + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + + return iterator(node); + } #endif #if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES diff --git a/groups/bsl/bslstl/bslstl_map_cpp03.h b/groups/bsl/bslstl/bslstl_map_cpp03.h index c73f33a8d4..12570abbb5 100644 --- a/groups/bsl/bslstl/bslstl_map_cpp03.h +++ b/groups/bsl/bslstl/bslstl_map_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 Tue Nov 26 06:40:32 2024 +// Generated on Wed Dec 11 07:38:13 2024 // Command line: sim_cpp11_features.pl bslstl_map.h #ifdef COMPILING_BSLSTL_MAP_H @@ -734,6 +734,43 @@ class map { BloombergLP::bslmf::MovableRef key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value, + pair >::type + insert_or_assign(BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) key, + BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj) + { + typedef pair Result; + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + key); + + if (!comparisonResult) { + iterator(insertLocation)->second = + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj); + return Result(iterator(insertLocation), false); + } + + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + + return Result(iterator(node), true); + } + template iterator insert_or_assign(const_iterator hint, const KEY& key, @@ -743,6 +780,47 @@ class map { iterator insert_or_assign(const_iterator hint, BloombergLP::bslmf::MovableRef key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); + + + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value, + iterator>::type + insert_or_assign(const_iterator hint, + BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) key, + BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj) + { + BloombergLP::bslalg::RbTreeNode *hintNode = + const_cast(hint.node()); + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + key, + hintNode); + + if (!comparisonResult) { + iterator(insertLocation)->second = + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj); + return iterator(insertLocation); + } + + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + + return iterator(node); + } // }}} END GENERATED CODE #if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES diff --git a/groups/bsl/bslstl/bslstl_map_test3.t.cpp b/groups/bsl/bslstl/bslstl_map_test3.t.cpp index bb48217952..53b4bd166d 100644 --- a/groups/bsl/bslstl/bslstl_map_test3.t.cpp +++ b/groups/bsl/bslstl/bslstl_map_test3.t.cpp @@ -744,7 +744,7 @@ struct TransparentComparator // non-const. So, for C++03, we make the conversion work with a const source. class TransparentlyComparable { // DATA -#if BLSL_COMPILERFEATURES_CPLUPLUS < 201103L +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L mutable #endif int d_conversionCount; // number of times `operator int` has been called @@ -769,7 +769,7 @@ class TransparentlyComparable { /// Return the current value of this object. operator int() -#if BLSL_COMPILERFEATURES_CPLUPLUS < 201103L +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L const #endif { @@ -777,6 +777,13 @@ class TransparentlyComparable { return d_value; } + /// return a count of the number of times this object has been converted to + /// an int. + void resetConversionCount() + { + d_conversionCount = 0; + } + // ACCESSORS /// Return the number of times `operator int` has been called. @@ -821,161 +828,183 @@ void testTransparentComparator(Container& container, typedef typename Container::const_iterator Iterator; typedef typename Container::size_type Count; - int expectedConversionCount = 0; + const int expectedConversionCount = isTransparent ? 0 : 1; TransparentlyComparable existingKey(initKeyValue); TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue : -100); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - // Testing `find`. + { + // Testing `find`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + const Iterator EXISTING_F = container.find(existingKey); + ASSERT(container.end() != EXISTING_F); + ASSERT(existingKey.value() == EXISTING_F->first); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const Iterator EXISTING_F = container.find(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_F = container.find(nonExistingKey); + ASSERT(container.end() == NON_EXISTING_F); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } + { + // Testing `contains`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + const bool EXISTING_CONTAINS = container.contains(existingKey); + ASSERT(true == EXISTING_CONTAINS); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - ASSERT(container.end() != EXISTING_F); - ASSERT(existingKey.value() == EXISTING_F->first); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const Iterator NON_EXISTING_F = container.find(nonExistingKey); - ASSERT(container.end() == NON_EXISTING_F); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); - - // Testing `contains`. - - const bool EXISTING_CONTAINS = container.contains(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); + ASSERT(false == NON_EXISTING_CONTAINS); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(true == EXISTING_CONTAINS); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); - ASSERT(false == NON_EXISTING_CONTAINS); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); - - // Testing `count`. + { + // Testing `count`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + const Count EXISTING_C = container.count(existingKey); + ASSERT(1 == EXISTING_C); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const Count EXISTING_C = container.count(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Count NON_EXISTING_C = container.count(nonExistingKey); + ASSERT(0 == NON_EXISTING_C); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(1 == EXISTING_C); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Count NON_EXISTING_C = container.count(nonExistingKey); - ASSERT(0 == NON_EXISTING_C); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `lower_bound`. + { + // Testing `lower_bound`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + const Iterator EXISTING_LB = container.lower_bound(existingKey); + ASSERT(existingKey.value() == EXISTING_LB->first); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const Iterator EXISTING_LB = container.lower_bound(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_LB = container.lower_bound(nonExistingKey); + ASSERT(container.begin() == NON_EXISTING_LB); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(EXISTING_F == EXISTING_LB); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Iterator NON_EXISTING_LB = container.lower_bound(nonExistingKey); - - ASSERT(container.begin() == NON_EXISTING_LB); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `upper_bound`. + { + // Testing `upper_bound`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + TransparentlyComparable upperBoundValue(initKeyValue + 1); + const Iterator EXPECTED_UB = container.find(upperBoundValue); + const Iterator EXISTING_UB = container.upper_bound(existingKey); + ASSERT(EXPECTED_UB == EXISTING_UB); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - TransparentlyComparable upperBoundValue(initKeyValue + 1); - const Iterator EXPECTED_UB = container.find(upperBoundValue); - const Iterator EXISTING_UB = container.upper_bound(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_UB = container.upper_bound(nonExistingKey); + ASSERT(container.begin() == NON_EXISTING_UB); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(EXPECTED_UB == EXISTING_UB); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Iterator NON_EXISTING_UB = container.upper_bound(nonExistingKey); - - ASSERT(container.begin() == NON_EXISTING_UB); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `equal_range`. + { + // Testing `equal_range`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - const bsl::pair EXISTING_ER = + const bsl::pair EXISTING_ER = container.equal_range(existingKey); - if (!isTransparent) { - ++expectedConversionCount; - } + ASSERT(EXISTING_ER.first != EXISTING_ER.second); + ASSERT(1 == static_cast( + bsl::distance(EXISTING_ER.first, EXISTING_ER.second))); + for (Iterator it = EXISTING_ER.first; it != EXISTING_ER.second; ++it) { + ASSERT(existingKey.value() == it->first); + } - ASSERT(EXISTING_LB == EXISTING_ER.first); - ASSERT(EXPECTED_UB == EXISTING_ER.second); - ASSERT(expectedConversionCount == existingKey.conversionCount()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const bsl::pair NON_EXISTING_ER = + const bsl::pair NON_EXISTING_ER = container.equal_range(nonExistingKey); - ASSERT(NON_EXISTING_LB == NON_EXISTING_ER.first); - ASSERT(NON_EXISTING_UB == NON_EXISTING_ER.second); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `at`. - if (!isTransparent) { - ++expectedConversionCount; + ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - try { - ASSERT(existingKey.value() == container.at(existingKey)); - } - catch (const std::out_of_range &) { - ASSERT(false); - } - - try { - (void) container.at(nonExistingKey); - ASSERT(false); - } - catch (const std::out_of_range &) { - } + { + // Testing `at`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - ASSERTV(expectedConversionCount, existingKey.conversionCount(), + try { + ASSERT(existingKey.value() == container.at(existingKey)); + } + catch (const std::out_of_range &) { + ASSERT(false); + } + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), - expectedConversionCount == nonExistingKey.conversionCount()); + + try { + (void) container.at(nonExistingKey); + ASSERT(false); + } + catch (const std::out_of_range &) { + } + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); + } } /// Search for a value equal to the specified `initKeyValue` in the /// specified `container`, and count the number of conversions expected /// based on the specified `isTransparent`. Since these tests can modify /// the container, we make a copy of it for each test. -template -void testTransparentComparatorMutable(const Container& container, - bool isTransparent, - int initKeyValue) +template +void testTransparentComparatorMutable(const t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { - typedef typename Container::size_type Count; + typedef typename t_CONTAINER::size_type Count; + typedef typename t_CONTAINER::iterator Iterator; - int expectedConversionCount = 0; + const int expectedConversionCount = isTransparent ? 0 : 1; const Count size = container.size(); - + TransparentlyComparable existingKey(initKeyValue); TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue : -100); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - { - // Testing `operator []`. + // Testing `operator []`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - if (!isTransparent) { - ++expectedConversionCount; - } - - Container c(container); + t_CONTAINER c(container); // with an existing key ASSERT(existingKey.value() == c[existingKey]); ASSERT(size == c.size()); @@ -983,7 +1012,7 @@ void testTransparentComparatorMutable(const Container& container, expectedConversionCount == existingKey.conversionCount()); // with a non-existing key - + // Note: We always get a conversion here; if we don't have a transparent // comparator, then the value gets converted, and when the lookup fails, // it gets inserted into the map. If we do have a transparent comparator, @@ -993,6 +1022,77 @@ void testTransparentComparatorMutable(const Container& container, ASSERT(size + 1 == c.size()); ASSERTV(1 == nonExistingKey.conversionCount()); } + + { + // Testing `insert_or_assign` (w/o hint). + typedef bsl::pair Ret; + + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + const Count size = container.size(); + + // with an existing key + Ret existingIA = c.insert_or_assign(existingKey, 1000); + ASSERT(size == c.size()); + ASSERT(!existingIA.second); + ASSERT(existingKey.value() == existingIA.first->first); + ASSERT(1000 == existingIA.first->second); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + Ret nonExistingIA = c.insert_or_assign(nonExistingKey, 1000); + ASSERT(size + 1 == c.size()); + ASSERT( nonExistingIA.second); + ASSERT(nonExistingKey.value() == nonExistingIA.first->first); + ASSERT(1000 == nonExistingIA.first->second); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } + + { + // Testing `insert_or_assign` (w/a hint). + + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + const Count size = container.size(); + + // with an existing key + Iterator existingIter = c.insert_or_assign(c.cbegin(), existingKey, 1000); + ASSERT(size == c.size()); + ASSERT(existingKey.value() == existingIter->first); + ASSERT(1000 == existingIter->second); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + Iterator nonExistingIter = c.insert_or_assign(c.cbegin(), nonExistingKey, 1000); + ASSERT(size + 1 == c.size()); + ASSERT(nonExistingKey.value() == nonExistingIter->first); + ASSERT(1000 == nonExistingIter->second); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } } // ==================================================== diff --git a/groups/bsl/bslstl/bslstl_set.h b/groups/bsl/bslstl/bslstl_set.h index c5e25bb7c7..23029add92 100644 --- a/groups/bsl/bslstl/bslstl_set.h +++ b/groups/bsl/bslstl/bslstl_set.h @@ -975,6 +975,47 @@ class set { pair insert( BloombergLP::bslmf::MovableRef value); +#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES + /// Insert the specified `value` into this set if a key equivalent to + /// `value` does not already exist in this set; otherwise, if a key + /// equivalent to `value` already exists in this set, this method has no + /// effect. `value` is left in a valid but unspecified state. Return a + /// pair whose `first` member is an iterator referring to the (possibly + /// newly inserted) `value_type` object in this set that is equivalent + /// to `value`, and whose `second` member is `true` if a new value was + /// inserted, and `false` if the key was already present. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + , pair >::type + insert(LOOKUP_KEY&& value) + { + typedef pair Result; + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + value); + if (!comparisonResult) { + return Result(iterator(insertLocation), false); // RETURN + } + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + return Result(iterator(node), true); + } +#endif + /// Insert the specified `value` into this set (in amortized constant /// time if the specified `hint` is a valid immediate successor to /// `value`), if a key equivalent to `value` does not already exist in @@ -1005,6 +1046,58 @@ class set { iterator insert(const_iterator hint, BloombergLP::bslmf::MovableRef value); +#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES + /// Insert the specified `value` into this set if a key equivalent to + /// `value` does not already exist in this set; otherwise, if a key + /// equivalent to `value` already exists in this set, this method has no + /// effect. `value` is left in a valid but unspecified state. Return + /// an iterator referring to the (possibly newly inserted) `value_type` + /// object in this set that is equivalent to `value`. The average and + /// worst case complexity of this operation is not affected by the + /// specified `hint`. This method requires that the (template + /// parameter) type `KEY` be `move-insertable` (see {Requirements on + /// `KEY`}) into this set. The behavior is undefined unless `hint` is + /// an iterator in the range `[begin() .. end()]` (both endpoints + /// included). Note that `hint` is ignored (other than possibly + /// asserting its validity in some build modes). + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && !bsl::is_convertible::value + && !bsl::is_convertible::value + , iterator>::type + insert(const_iterator hint, LOOKUP_KEY&& value) + { + BloombergLP::bslalg::RbTreeNode *hintNode = + const_cast(hint.node()); + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + value, + hintNode); + if (!comparisonResult) { + return iterator(insertLocation); // RETURN + } + + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + return iterator(node); + } +#endif + /// Insert into this set the value of each `value_type` object in the /// range starting at the specified `first` iterator and ending /// immediately before the specified `last` iterator, if a key diff --git a/groups/bsl/bslstl/bslstl_set_cpp03.h b/groups/bsl/bslstl/bslstl_set_cpp03.h index 7139889157..b9ae8a48d1 100644 --- a/groups/bsl/bslstl/bslstl_set_cpp03.h +++ b/groups/bsl/bslstl/bslstl_set_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 Wed Dec 11 07:29:25 2024 // Command line: sim_cpp11_features.pl bslstl_set.h #ifdef COMPILING_BSLSTL_SET_H @@ -419,6 +419,39 @@ class set { pair insert( BloombergLP::bslmf::MovableRef value); +// {{{ BEGIN GENERATED CODE +// The generated code below is a workaround for the absence of perfect +// forwarding in some compilers. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + , pair >::type + insert(BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) value) + { + typedef pair Result; + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + value); + if (!comparisonResult) { + return Result(iterator(insertLocation), false); + } + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + return Result(iterator(node), true); + } +// }}} END GENERATED CODE + /// Insert the specified `value` into this set (in amortized constant /// time if the specified `hint` is a valid immediate successor to /// `value`), if a key equivalent to `value` does not already exist in @@ -449,6 +482,48 @@ class set { iterator insert(const_iterator hint, BloombergLP::bslmf::MovableRef value); +// {{{ BEGIN GENERATED CODE +// The generated code below is a workaround for the absence of perfect +// forwarding in some compilers. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && !bsl::is_convertible::value + && !bsl::is_convertible::value + , iterator>::type + insert(const_iterator hint, + BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) value) + { + BloombergLP::bslalg::RbTreeNode *hintNode = + const_cast(hint.node()); + + int comparisonResult; + BloombergLP::bslalg::RbTreeNode *insertLocation = + BloombergLP::bslalg::RbTreeUtil::findUniqueInsertLocation( + &comparisonResult, + &d_tree, + this->comparator(), + value, + hintNode); + if (!comparisonResult) { + return iterator(insertLocation); + } + + BloombergLP::bslalg::RbTreeNode *node = + nodeFactory().emplaceIntoNewNode( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + + BloombergLP::bslalg::RbTreeUtil::insertAt(&d_tree, + insertLocation, + comparisonResult < 0, + node); + return iterator(node); + } +// }}} END GENERATED CODE + /// Insert into this set the value of each `value_type` object in the /// range starting at the specified `first` iterator and ending /// immediately before the specified `last` iterator, if a key @@ -479,30 +554,30 @@ class set { #ifndef BSLSTL_SET_VARIADIC_LIMIT #define BSLSTL_SET_VARIADIC_LIMIT 10 #endif -#ifndef BSLSTL_SET_VARIADIC_LIMIT_A -#define BSLSTL_SET_VARIADIC_LIMIT_A BSLSTL_SET_VARIADIC_LIMIT +#ifndef BSLSTL_SET_VARIADIC_LIMIT_C +#define BSLSTL_SET_VARIADIC_LIMIT_C BSLSTL_SET_VARIADIC_LIMIT #endif -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 0 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 0 pair emplace( ); -#endif // BSLSTL_SET_VARIADIC_LIMIT_A >= 0 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 0 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 1 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 1 template pair emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); -#endif // BSLSTL_SET_VARIADIC_LIMIT_A >= 1 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 1 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 2 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 2 template pair emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); -#endif // BSLSTL_SET_VARIADIC_LIMIT_A >= 2 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 2 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 3 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 3 template @@ -510,9 +585,9 @@ class set { 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_SET_VARIADIC_LIMIT_A >= 3 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 3 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 4 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 4 template = 4 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 4 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 5 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 5 template = 5 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 5 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 6 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 6 template = 6 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 6 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 7 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 7 template = 7 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 7 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 8 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 8 template = 8 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 8 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 9 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 9 template = 9 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 9 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 10 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 10 template = 10 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 10 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 0 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 0 iterator emplace_hint(const_iterator hint); -#endif // BSLSTL_SET_VARIADIC_LIMIT_A >= 0 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 0 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 1 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 1 template iterator emplace_hint(const_iterator hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); -#endif // BSLSTL_SET_VARIADIC_LIMIT_A >= 1 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 1 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 2 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 2 template iterator emplace_hint(const_iterator hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); -#endif // BSLSTL_SET_VARIADIC_LIMIT_A >= 2 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 2 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 3 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 3 template @@ -665,9 +740,9 @@ class set { 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_SET_VARIADIC_LIMIT_A >= 3 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 3 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 4 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 4 template = 4 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 4 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 5 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 5 template = 5 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 5 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 6 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 6 template = 6 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 6 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 7 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 7 template = 7 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 7 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 8 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 8 template = 8 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 8 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 9 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 9 template = 9 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 9 -#if BSLSTL_SET_VARIADIC_LIMIT_A >= 10 +#if BSLSTL_SET_VARIADIC_LIMIT_C >= 10 template = 10 +#endif // BSLSTL_SET_VARIADIC_LIMIT_C >= 10 #else // The generated code below is a workaround for the absence of perfect @@ -2167,10 +2242,10 @@ void set::insert(std::initializer_list values) #ifndef BSLSTL_SET_VARIADIC_LIMIT #define BSLSTL_SET_VARIADIC_LIMIT 10 #endif -#ifndef BSLSTL_SET_VARIADIC_LIMIT_B -#define BSLSTL_SET_VARIADIC_LIMIT_B BSLSTL_SET_VARIADIC_LIMIT +#ifndef BSLSTL_SET_VARIADIC_LIMIT_D +#define BSLSTL_SET_VARIADIC_LIMIT_D BSLSTL_SET_VARIADIC_LIMIT #endif -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 0 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 0 template inline pair::iterator, bool> @@ -2196,9 +2271,9 @@ set::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 0 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 1 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 1 template template inline @@ -2225,9 +2300,9 @@ set::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 1 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 2 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 2 template template @@ -2257,9 +2332,9 @@ set::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 2 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 3 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 3 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 3 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 4 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 4 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 4 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 5 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 5 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 5 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 6 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 6 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 6 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 7 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 7 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 7 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 8 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 8 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 8 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 9 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 9 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 9 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 10 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 10 template template ::emplace( node); return pair(iterator(node), true); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 10 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 10 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 0 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 0 template inline typename set::iterator @@ -2653,9 +2728,9 @@ set::emplace_hint(const_iterator hint) node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 0 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 1 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 1 template template inline @@ -2686,9 +2761,9 @@ set::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 1 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 2 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 2 template template @@ -2722,9 +2797,9 @@ set::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 2 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 3 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 3 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 3 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 4 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 4 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 4 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 5 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 5 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 5 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 6 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 6 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 6 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 7 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 7 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 7 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 8 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 8 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 8 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 9 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 9 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 9 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_SET_VARIADIC_LIMIT_B >= 10 +#if BSLSTL_SET_VARIADIC_LIMIT_D >= 10 template template ::emplace_hint(const_iterator hint, node); return iterator(node); } -#endif // BSLSTL_SET_VARIADIC_LIMIT_B >= 10 +#endif // BSLSTL_SET_VARIADIC_LIMIT_D >= 10 #else // The generated code below is a workaround for the absence of perfect diff --git a/groups/bsl/bslstl/bslstl_set_test.t.cpp b/groups/bsl/bslstl/bslstl_set_test.t.cpp index 035f82493c..38e44d5b70 100644 --- a/groups/bsl/bslstl/bslstl_set_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_set_test.t.cpp @@ -874,6 +874,9 @@ struct TransparentComparator class TransparentlyComparable { // DATA +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L + mutable +#endif int d_conversionCount; // number of times `operator int` has been called int d_value; // the value @@ -895,11 +898,21 @@ class TransparentlyComparable { /// Return the current value of this object. operator int() +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L + const +#endif { ++d_conversionCount; return d_value; } + /// return a count of the number of times this object has been converted to + /// an int. + void resetConversionCount() + { + d_conversionCount = 0; + } + // ACCESSORS /// Return the number of times `operator int` has been called. @@ -936,115 +949,222 @@ class TransparentlyComparable { /// as a sort of universal reference. Conceptually, the object remains /// constant, but we want to test `const`-qualified and /// non-`const`-qualified overloads. -template -void testTransparentComparator(Container& container, - bool isTransparent, - int initKeyValue) +template +void testTransparentComparator(t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename t_CONTAINER::const_iterator Iterator; + typedef typename t_CONTAINER::size_type Count; - int expectedConversionCount = 0; + const int expectedConversionCount = isTransparent ? 0 : 1; TransparentlyComparable existingKey(initKeyValue); TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue : -100); - ASSERT(existingKey.conversionCount() == expectedConversionCount); + { + // Testing `find`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `find`. + const Iterator EXISTING_F = container.find(existingKey); + ASSERT(container.end() != EXISTING_F); + ASSERT(existingKey.value() == *EXISTING_F); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const Iterator EXISTING_F = container.find(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_F = container.find(nonExistingKey); + ASSERT(container.end() == NON_EXISTING_F); + ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(container.end() != EXISTING_F); - ASSERT(existingKey.value() == *EXISTING_F); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const Iterator NON_EXISTING_F = container.find(nonExistingKey); - ASSERT(container.end() == NON_EXISTING_F); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + { + // Testing `contains`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `contains`. + const bool EXISTING_CONTAINS = container.contains(existingKey); + ASSERT(true == EXISTING_CONTAINS); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const bool EXISTING_CONTAINS = container.contains(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); + ASSERT(false == NON_EXISTING_CONTAINS); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(true == EXISTING_CONTAINS); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); - ASSERT(false == NON_EXISTING_CONTAINS); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + { + // Testing `count`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `count`. + const Count EXISTING_C = container.count(existingKey); + ASSERT(1 == EXISTING_C); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const Count EXISTING_C = container.count(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Count NON_EXISTING_C = container.count(nonExistingKey); + ASSERT(0 == NON_EXISTING_C); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(1 == EXISTING_C); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Count NON_EXISTING_C = container.count(nonExistingKey); - ASSERT(0 == NON_EXISTING_C); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + { + // Testing `lower_bound`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `lower_bound`. + const Iterator EXISTING_LB = container.lower_bound(existingKey); + ASSERT(existingKey.value() == *EXISTING_LB); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - const Iterator EXISTING_LB = container.lower_bound(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_LB = container.lower_bound(nonExistingKey); + ASSERT(container.begin() == NON_EXISTING_LB); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(EXISTING_F == EXISTING_LB); - ASSERT(expectedConversionCount == existingKey.conversionCount()); + { + // Testing `upper_bound`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - const Iterator NON_EXISTING_LB = container.lower_bound(nonExistingKey); + TransparentlyComparable upperBoundValue(initKeyValue + 1); + const Iterator EXPECTED_UB = container.find(upperBoundValue); + const Iterator EXISTING_UB = container.upper_bound(existingKey); - ASSERT(container.begin() == NON_EXISTING_LB); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + ASSERT(EXPECTED_UB == EXISTING_UB); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - // Testing `upper_bound`. + const Iterator NON_EXISTING_UB = container.upper_bound(nonExistingKey); - TransparentlyComparable upperBoundValue(initKeyValue + 1); - const Iterator EXPECTED_UB = container.find(upperBoundValue); - const Iterator EXISTING_UB = container.upper_bound(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + ASSERT(container.begin() == NON_EXISTING_UB); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(EXPECTED_UB == EXISTING_UB); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Iterator NON_EXISTING_UB = container.upper_bound(nonExistingKey); - - ASSERT(container.begin() == NON_EXISTING_UB); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `equal_range`. + { + // Testing `equal_range`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - const bsl::pair EXISTING_ER = + const bsl::pair EXISTING_ER = container.equal_range(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + ASSERT(EXISTING_ER.first != EXISTING_ER.second); + ASSERT(1 == bsl::distance(EXISTING_ER.first, EXISTING_ER.second)); + ASSERT(existingKey.value() == *EXISTING_ER.first); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + const bsl::pair NON_EXISTING_ER = + container.equal_range(nonExistingKey); + ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); + ASSERTV(isTransparent, + expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } +} - ASSERT(EXISTING_LB == EXISTING_ER.first); - ASSERT(EXPECTED_UB == EXISTING_ER.second); - ASSERT(expectedConversionCount == existingKey.conversionCount()); +/// specified `container`, and count the number of conversions expected +/// based on the specified `isTransparent`. Unlike `testTransparentComparator` +/// above, this method tests methods that may modify the container, so we make +/// copies of the container. +template +void testTransparentComparatorMutable(const t_CONTAINER& container, + bool isTransparent, + int initKeyValue) +{ + typedef typename t_CONTAINER::size_type Count; + typedef typename t_CONTAINER::iterator Iterator; - const bsl::pair NON_EXISTING_ER = - container.equal_range(nonExistingKey); + const int expectedConversionCount = isTransparent ? 0 : 1; - ASSERT(NON_EXISTING_LB == NON_EXISTING_ER.first); - ASSERT(NON_EXISTING_UB == NON_EXISTING_ER.second); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + TransparentlyComparable existingKey(initKeyValue); + TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue + : -100); + + { + // Testing `insert(value)`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + bsl::pair ret; + const Count size = c.size(); + + // with an existing key + ret = c.insert(existingKey); + ASSERT(!ret.second); + ASSERT(existingKey.value() == *ret.first); + ASSERT(size == c.size()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + ret = c.insert(nonExistingKey); + ASSERT(ret.second); + ASSERT(size + 1 == c.size()); + ASSERT(nonExistingKey.value() == *ret.first); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } + + // Testing `insert(hint, value)`. + { + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + Iterator ret; + const Count size = c.size(); + + // with an existing key + ret = c.insert(c.begin(), existingKey); + ASSERT(existingKey.value() == *ret); + ASSERT(size == c.size()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + ret = c.insert(c.begin(), nonExistingKey); + ASSERT(nonExistingKey.value() == *ret); + ASSERT(size + 1 == c.size()); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } } // ==================================================== @@ -8530,7 +8650,8 @@ int main(int argc, char *argv[]) if (veryVerbose) { printf("\tTesting mutable non-transparent set.\n"); } - testTransparentComparator(mXNT, false, VALUE); + testTransparentComparator (mXNT, false, VALUE); + testTransparentComparatorMutable(mXNT, false, VALUE); if (veryVerbose) { printf("\tTesting const transparent set.\n"); @@ -8540,7 +8661,8 @@ int main(int argc, char *argv[]) if (veryVerbose) { printf("\tTesting mutable transparent set.\n"); } - testTransparentComparator(mXT, true, VALUE); + testTransparentComparator (mXT, true, VALUE); + testTransparentComparatorMutable(mXT, true, VALUE); } } break; case 33: { diff --git a/groups/bsl/bslstl/bslstl_unorderedmap.h b/groups/bsl/bslstl/bslstl_unorderedmap.h index 84a63f0b88..5930da66bd 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmap.h +++ b/groups/bsl/bslstl/bslstl_unorderedmap.h @@ -1733,6 +1733,33 @@ class unordered_map { BloombergLP::bslmf::MovableRef key, BDE_OTHER_TYPE&& obj); + /// If a key equivalent to the specified `key` already exists in this + /// unordered_map, assign the specified `obj` to the value associated + /// with that key, and return a pair containing an iterator referring to + /// the existing item and `false`. Otherwise, insert into this map a + /// newly-created `value_type` object, constructed from + /// `(std::forward(key), std::forward(obj)...))`, + /// and return a pair containing an iterator referring to the + /// newly-created entry and `true`. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , pair >::type + insert_or_assign(LOOKUP_KEY&& key, BDE_OTHER_TYPE&& obj) + { + typedef bsl::pair ResultType; + bool isInsertedFlag = false; + HashTableLink *result = d_impl.insertOrAssignTransparent( + &isInsertedFlag, + NULL, + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + return ResultType(iterator(result), isInsertedFlag); + } + /// If a key equivalent to the specified `key` already exists in this /// unordered_map, assign the specified `obj` to the value associated /// with that key, and return an iterator referring to the existing @@ -1762,6 +1789,32 @@ class unordered_map { BloombergLP::bslmf::MovableRef key, BDE_OTHER_TYPE&& obj); + /// If a key equivalent to the specified `key` already exists in this + /// unordered_map, assign the specified `obj` to the value associated + /// with that key, and return an iterator referring to the existing + /// item. Otherwise, insert into this map a newly-created `value_type` + /// object, constructed from + /// `(std::forward(key), std::forward(obj)...))`, + /// and return an iterator referring to the newly-created entry. Use + /// the specified `hint` as a starting point for checking to see if the + /// key already in the unordered_map. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , iterator>::type + insert_or_assign(const_iterator hint, LOOKUP_KEY&& key, BDE_OTHER_TYPE&& obj) + { + bool isInsertedFlag = false; + HashTableLink *result = d_impl.insertOrAssignTransparent( + &isInsertedFlag, + hint.node(), + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + return iterator(result); + } #endif /// Return a pair of iterators providing modifiable access to the diff --git a/groups/bsl/bslstl/bslstl_unorderedmap_cpp03.h b/groups/bsl/bslstl/bslstl_unorderedmap_cpp03.h index 8e2acf2cad..deb86408ea 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 Thu Nov 14 08:33:27 2024 +// Generated on Wed Dec 11 07:38:13 2024 // Command line: sim_cpp11_features.pl bslstl_unorderedmap.h #ifdef COMPILING_BSLSTL_UNORDEREDMAP_H @@ -1017,34 +1017,7 @@ class unordered_map { void insert(std::initializer_list values); #endif -#if BSLS_COMPILERFEATURES_SIMULATE_VARIADIC_TEMPLATES // {{{ BEGIN GENERATED CODE -// Command line: sim_cpp11_features.pl bslstl_unorderedmap.h -#ifndef BSLSTL_UNORDEREDMAP_VARIADIC_LIMIT -#define BSLSTL_UNORDEREDMAP_VARIADIC_LIMIT 10 -#endif -#ifndef BSLSTL_UNORDEREDMAP_VARIADIC_LIMIT_C -#define BSLSTL_UNORDEREDMAP_VARIADIC_LIMIT_C BSLSTL_UNORDEREDMAP_VARIADIC_LIMIT -#endif - template - pair insert_or_assign(const KEY& key, - BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); - - template - pair insert_or_assign( - BloombergLP::bslmf::MovableRef key, - BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); - - template - iterator insert_or_assign(const_iterator hint, - const KEY& key, - BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); - - template - iterator insert_or_assign(const_iterator hint, - BloombergLP::bslmf::MovableRef key, - BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); -#else // The generated code below is a workaround for the absence of perfect // forwarding in some compilers. template @@ -1056,6 +1029,24 @@ class unordered_map { BloombergLP::bslmf::MovableRef key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , pair >::type + insert_or_assign(BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) key, + BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj) + { + typedef bsl::pair ResultType; + bool isInsertedFlag = false; + HashTableLink *result = d_impl.insertOrAssignTransparent( + &isInsertedFlag, + NULL, + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + return ResultType(iterator(result), isInsertedFlag); + } + template iterator insert_or_assign(const_iterator hint, const KEY& key, @@ -1066,8 +1057,24 @@ class unordered_map { BloombergLP::bslmf::MovableRef key, BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj); + template + typename bsl::enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + , iterator>::type + insert_or_assign(const_iterator hint, + BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) key, + BSLS_COMPILERFEATURES_FORWARD_REF(BDE_OTHER_TYPE) obj) + { + bool isInsertedFlag = false; + HashTableLink *result = d_impl.insertOrAssignTransparent( + &isInsertedFlag, + hint.node(), + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, key), + BSLS_COMPILERFEATURES_FORWARD(BDE_OTHER_TYPE, obj)); + return iterator(result); + } // }}} END GENERATED CODE -#endif /// Return a pair of iterators providing modifiable access to the /// sequence of `value_type` objects in this unordered map having the diff --git a/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp b/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp index 4bc6fc6877..83b9d588b4 100644 --- a/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedmap_test.t.cpp @@ -1449,7 +1449,7 @@ TestIncompleteType::~TestIncompleteType() // non-const. So, for C++03, we make the conversion work with a const source. class TransparentlyComparable { // DATA -#if BLSL_COMPILERFEATURES_CPLUPLUS < 201103L +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L mutable #endif int d_conversionCount; // number of times `operator int` has been called @@ -1473,7 +1473,7 @@ class TransparentlyComparable { /// Return the current value of this object. operator int() -#if BLSL_COMPILERFEATURES_CPLUPLUS < 201103L +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L const #endif { @@ -1481,6 +1481,13 @@ class TransparentlyComparable { return d_value; } + /// return a count of the number of times this object has been converted to + /// an int. + void resetConversionCount() + { + d_conversionCount = 0; + } + // ACCESSORS /// Return the number of times `operator int` has been called. @@ -1591,179 +1598,177 @@ struct HashAnyStr /// `const`-qualified type, we are using the "reference" here as a sort of /// universal reference; conceptually, the object remains constant, but we /// want to test `const`-qualified and non-`const`-qualified overloads. -template -void testTransparentComparator(Container& container, - bool isTransparent, - int initKeyValue) +template +void testTransparentComparator(t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { - typedef typename Container::const_local_iterator LocalIterator; - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename t_CONTAINER::const_local_iterator LocalIterator; + typedef typename t_CONTAINER::const_iterator Iterator; + typedef typename t_CONTAINER::size_type Count; - int expectedConversionCount = 0; + const int expectedConversionCount = isTransparent ? 0 : 1; TransparentlyComparable existingKey(initKeyValue); TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue : -100); + { + // Testing `find`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - ASSERT(existingKey.conversionCount() == expectedConversionCount); + const Iterator EXISTING_F = container.find(existingKey); - // Testing `find`. + ASSERT(container.end() != EXISTING_F); + ASSERT(existingKey.value() == EXISTING_F->first); + ASSERT(existingKey.conversionCount() == expectedConversionCount); - const Iterator EXISTING_F = container.find(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_F = container.find(nonExistingKey); + ASSERT(container.end() == NON_EXISTING_F); + ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); } - ASSERT(container.end() != EXISTING_F); - ASSERT(existingKey.value() == EXISTING_F->first); - ASSERT(existingKey.conversionCount() == expectedConversionCount); + { + // Testing `contains`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - const Iterator NON_EXISTING_F = container.find(nonExistingKey); - ASSERT(container.end() == NON_EXISTING_F); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + const bool EXISTING_CONTAINS = container.contains(existingKey); - // Testing `contains`. + ASSERT(true == EXISTING_CONTAINS); + ASSERT(existingKey.conversionCount() == expectedConversionCount); - const bool EXISTING_CONTAINS = container.contains(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); + ASSERT(false == NON_EXISTING_CONTAINS); + ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); } - ASSERT(true == EXISTING_CONTAINS); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); - ASSERT(false == NON_EXISTING_CONTAINS); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + { + // Testing `count`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `count`. + const Count EXPECTED_C = 1; + const Count EXISTING_C = container.count(existingKey); - const Count EXPECTED_C = 1; - const Count EXISTING_C = container.count(existingKey); + ASSERT(EXPECTED_C == EXISTING_C); + ASSERT(expectedConversionCount == existingKey.conversionCount()); - if (!isTransparent) { - ++expectedConversionCount; + const Count NON_EXISTING_C = container.count(nonExistingKey); + ASSERT(0 == NON_EXISTING_C); + ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(EXPECTED_C == EXISTING_C); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Count NON_EXISTING_C = container.count(nonExistingKey); - ASSERT(0 == NON_EXISTING_C); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `equal_range`. + { + // Testing `equal_range`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - const bsl::pair EXISTING_ER = + const bsl::pair EXISTING_ER = container.equal_range(existingKey); - if (!isTransparent) { - ++expectedConversionCount; - } - - ASSERT(expectedConversionCount == existingKey.conversionCount()); - ASSERT(EXPECTED_C == - static_cast(bsl::distance(EXISTING_ER.first, EXISTING_ER.second))); - - for (Iterator it = EXISTING_ER.first; it != EXISTING_ER.second; ++it) { - ASSERT(existingKey.value() == it->first); - } + ASSERT(expectedConversionCount == existingKey.conversionCount()); + ASSERT(1 == static_cast( + bsl::distance(EXISTING_ER.first, EXISTING_ER.second))); - const bsl::pair NON_EXISTING_ER = - container.equal_range(nonExistingKey); - ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); + for (Iterator it = EXISTING_ER.first; it != EXISTING_ER.second; ++it) { + ASSERT(existingKey.value() == it->first); + } - // Testing `at`. - if (!isTransparent) { - ++expectedConversionCount; + const bsl::pair NON_EXISTING_ER = + container.equal_range(nonExistingKey); + ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); + ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); } - try { - ASSERT(existingKey.value() == container.at(existingKey)); - } - catch (const std::out_of_range &) { - ASSERT(false); - } + { + // Testing `at`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - try { - (void) container.at(nonExistingKey); - ASSERT(false); - } - catch (const std::out_of_range &) { - } - ASSERTV(expectedConversionCount, existingKey.conversionCount(), - expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), - expectedConversionCount == nonExistingKey.conversionCount()); + try { + ASSERT(existingKey.value() == container.at(existingKey)); + } + catch (const std::out_of_range &) { + ASSERT(false); + } - // Testing `bucket`. - const Count bucketFound = container.bucket(existingKey); - const Count bucketNotFound = container.bucket(nonExistingKey); + try { + (void) container.at(nonExistingKey); + ASSERT(false); + } + catch (const std::out_of_range &) { + } - if (!isTransparent) { - ++expectedConversionCount; + ASSERTV(expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); } - 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; + { + // Testing `bucket`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + const Count bucketFound = container.bucket(existingKey); + const Count bucketNotFound = container.bucket(nonExistingKey); + + 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 t_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); + 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; + 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); } - ASSERT(!found_it); } /// Search for a value equal to the specified `initKeyValue` in the /// specified `container`, and count the number of conversions expected /// based on the specified `isTransparent`. Since these tests can modify /// the container, we make a copy of it for each test. -template -void testTransparentComparatorMutable(const Container& container, - bool isTransparent, - int initKeyValue) +template +void testTransparentComparatorMutable(const t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { - typedef typename Container::size_type Count; + typedef typename t_CONTAINER::size_type Count; + typedef typename t_CONTAINER::iterator Iterator; - int expectedConversionCount = 0; - const Count size = container.size(); + const int expectedConversionCount = isTransparent ? 0 : 1; TransparentlyComparable existingKey(initKeyValue); TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue : -100); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - { // Testing `operator []`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - Container c(container); - - if (!isTransparent) { - ++expectedConversionCount; - } + t_CONTAINER c(container); + const Count size = container.size(); // with an existing key ASSERT(existingKey.value() == c[existingKey]); @@ -1774,14 +1779,87 @@ void testTransparentComparatorMutable(const Container& container, // with a non-existing key - // Note: We always get a conversion here; if we don't have a transparent - // comparator, then the value gets converted, and when the lookup fails, - // it gets inserted into the map. If we do have a transparent comparator, - // the lookup is done w/o conversion, but then the value gets converted - // in order to put it into the map. + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. (void) c[nonExistingKey]; ASSERT(size + 1 == c.size()); - ASSERT(1 == nonExistingKey.conversionCount()); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } + + { + // Testing `insert_or_assign` (w/o hint). + typedef bsl::pair Ret; + + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + const Count size = container.size(); + + // with an existing key + Ret existingIA = c.insert_or_assign(existingKey, 1000); + ASSERT(size == c.size()); + ASSERT(!existingIA.second); + ASSERT(existingKey.value() == existingIA.first->first); + ASSERT(1000 == existingIA.first->second); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + Ret nonExistingIA = c.insert_or_assign(nonExistingKey, 1000); + ASSERT(size + 1 == c.size()); + ASSERT( nonExistingIA.second); + ASSERT(nonExistingKey.value() == nonExistingIA.first->first); + ASSERT(1000 == nonExistingIA.first->second); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } + + { + // Testing `insert_or_assign` (w/a hint). + + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + const Count size = container.size(); + + // with an existing key + Iterator existingIter = c.insert_or_assign(c.cbegin(), existingKey, 1000); + ASSERT(size == c.size()); + ASSERT(existingKey.value() == existingIter->first); + ASSERT(1000 == existingIter->second); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + Iterator nonExistingIter = c.insert_or_assign(c.cbegin(), nonExistingKey, 1000); + ASSERT(size + 1 == c.size()); + ASSERT(nonExistingKey.value() == nonExistingIter->first); + ASSERT(1000 == nonExistingIter->second); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); } } diff --git a/groups/bsl/bslstl/bslstl_unorderedset.h b/groups/bsl/bslstl/bslstl_unorderedset.h index cf26a00179..b336097232 100644 --- a/groups/bsl/bslstl/bslstl_unorderedset.h +++ b/groups/bsl/bslstl/bslstl_unorderedset.h @@ -1009,6 +1009,34 @@ class unordered_set { pair insert( BloombergLP::bslmf::MovableRef value); +#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES + /// Insert the specified `value` into this set if a key equivalent to + /// `value` does not already exist in this set; otherwise, if a key + /// equivalent to `value` already exists in this set, this method has no + /// effect. `value` is left in a valid but unspecified state. Return a + /// pair whose `first` member is an iterator referring to the (possibly + /// newly inserted) `value_type` object in this set that is equivalent + /// to `value`, and whose `second` member is `true` if a new value was + /// inserted, and `false` if the key was already present. + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + pair >::type + insert(LOOKUP_KEY&& value) + { + typedef bsl::pair ResultType; + bool isInsertedFlag = false; + HashTableLink *result = + d_impl.insertIfMissingTransparent( + &isInsertedFlag, + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + return ResultType(iterator(result), isInsertedFlag); + } +#endif + /// Insert the specified `value` into this set if a key equivalent to /// `value` does not already exist in this set; otherwise, if a key /// equivalent to `value` already exists in this set, this method has no @@ -1039,6 +1067,36 @@ class unordered_set { iterator insert(const_iterator hint, BloombergLP::bslmf::MovableRef value); +#if !BSLS_COMPILERFEATURES_SIMULATE_CPP11_FEATURES + /// Insert the specified `value` into this set if a key equivalent to + /// `value` does not already exist in this set; otherwise, if a key + /// equivalent to `value` already exists in this set, this method has no + /// effect. `value` is left in a valid but unspecified state. Return + /// an iterator referring to the (possibly newly inserted) `value_type` + /// object in this set that is equivalent to `value`. The average and + /// worst case complexity of this operation is not affected by the + /// specified `hint`. This method requires that the (template + /// parameter) type `KEY` be `move-insertable` (see {Requirements on + /// `KEY`}) into this set. The behavior is undefined unless `hint` is + /// an iterator in the range `[begin() .. end()]` (both endpoints + /// included). Note that `hint` is ignored (other than possibly + /// asserting its validity in some build modes). + /// + /// Note: implemented inline due to Sun CC compilation error. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + && !bsl::is_convertible::value + && !bsl::is_convertible::value + , iterator>::type + insert(const_iterator, LOOKUP_KEY&& value) + { + return this->insert( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)).first; + } +#endif + /// Insert into this set the value of each `value_type` object in the /// range starting at the specified `first` iterator and ending /// immediately before the specified `last` iterator, if a key @@ -1163,6 +1221,8 @@ class unordered_set { /// `key`, if such an entry exists, and the past-the-end (`end`) /// iterator otherwise. The behavior is undefined unless `key` is /// equivalent to at most one element in this unordered set. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1170,7 +1230,6 @@ class unordered_set { iterator>::type find(const LOOKUP_KEY& key) { - // Note: implemented inline due to Sun CC compilation error. return iterator(d_impl.find(key)); } @@ -1190,6 +1249,8 @@ class unordered_set { /// undefined unless `key` is equivalent to at most one element in this /// unordered set. Note that since an unordered set maintains unique /// keys, the range will contain at most one element. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1197,7 +1258,6 @@ class unordered_set { pair >::type equal_range(const LOOKUP_KEY& key) { - // Note: implemented inline due to Sun CC compilation error. typedef bsl::pair ResultType; HashTableLink *first = d_impl.find(key); @@ -1271,6 +1331,8 @@ class unordered_set { /// Return `true` if this unordered set contains an element whose key is /// equivalent to the specified `key`. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value && @@ -1279,7 +1341,6 @@ class unordered_set { bool>::type contains(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error return find(key) != end(); } @@ -1310,6 +1371,8 @@ class unordered_set { /// specified `key`, if such an entry exists, and the past-the-end /// (`end`) iterator otherwise. The behavior is undefined unless `key` /// is equivalent to at most one element in this unordered set. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1317,7 +1380,6 @@ class unordered_set { const_iterator>::type find(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error. return const_iterator(d_impl.find(key)); } @@ -1332,6 +1394,8 @@ class unordered_set { /// undefined unless `key` is equivalent to at most one element in this /// unordered set. Note that since an unordered set maintains unique /// keys, the returned value will be either 0 or 1. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1339,7 +1403,6 @@ class unordered_set { size_type>::type count(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error. return d_impl.find(key) != 0; } @@ -1359,6 +1422,8 @@ class unordered_set { /// undefined unless `key` is equivalent to at most one element in this /// unordered set. Note that since an unordered set maintains unique /// keys, the range will contain at most one element. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1366,7 +1431,6 @@ class unordered_set { pair >::type equal_range(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error. typedef bsl::pair ResultType; HashTableLink *first = d_impl.find(key); diff --git a/groups/bsl/bslstl/bslstl_unorderedset.t.cpp b/groups/bsl/bslstl/bslstl_unorderedset.t.cpp index bc42f4573d..d0d6bf368a 100644 --- a/groups/bsl/bslstl/bslstl_unorderedset.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedset.t.cpp @@ -201,7 +201,7 @@ using bsls::NameOf; // ---------------------------------------------------------------------------- // [ 1] BREATHING TEST // [ 2] default construction (only) -// [38] USAGE EXAMPLE +// [39] USAGE EXAMPLE // // TEST APPARATUS: GENERATOR FUNCTIONS //*[ 3] int ggg(unordered_set *object, const char *spec, int verbose); @@ -4717,7 +4717,7 @@ int main(int argc, char *argv[]) ASSERT(0 == bslma::Default::setDefaultAllocator(&defaultAllocator)); switch (test) { case 0: - case 38: { + case 39: { // -------------------------------------------------------------------- // USAGE EXAMPLE // @@ -4872,6 +4872,7 @@ if (verbose) { // See the material in {`bslstl_unorderedmap`|Example 2}. } break; + case 38: // falls through case 37: // falls through case 36: // falls through case 35: // falls through diff --git a/groups/bsl/bslstl/bslstl_unorderedset_cpp03.h b/groups/bsl/bslstl/bslstl_unorderedset_cpp03.h index d3808a4bf5..285831905a 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 Thu Nov 7 07:41:40 2024 +// Generated on Wed Dec 11 08:22:26 2024 // Command line: sim_cpp11_features.pl bslstl_unorderedset.h #ifdef COMPILING_BSLSTL_UNORDEREDSET_H @@ -414,6 +414,26 @@ class unordered_set { pair insert( BloombergLP::bslmf::MovableRef value); +// {{{ BEGIN GENERATED CODE +// The generated code below is a workaround for the absence of perfect +// forwarding in some compilers. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value, + pair >::type + insert(BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) value) + { + typedef bsl::pair ResultType; + bool isInsertedFlag = false; + HashTableLink *result = + d_impl.insertIfMissingTransparent( + &isInsertedFlag, + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)); + return ResultType(iterator(result), isInsertedFlag); + } +// }}} END GENERATED CODE + /// Insert the specified `value` into this set if a key equivalent to /// `value` does not already exist in this set; otherwise, if a key /// equivalent to `value` already exists in this set, this method has no @@ -444,6 +464,25 @@ class unordered_set { iterator insert(const_iterator hint, BloombergLP::bslmf::MovableRef value); +// {{{ BEGIN GENERATED CODE +// The generated code below is a workaround for the absence of perfect +// forwarding in some compilers. + template + typename enable_if< + BloombergLP::bslmf::IsTransparentPredicate::value + && BloombergLP::bslmf::IsTransparentPredicate::value + && !bsl::is_convertible::value + && !bsl::is_convertible::value + , iterator>::type + insert(const_iterator, BSLS_COMPILERFEATURES_FORWARD_REF(LOOKUP_KEY) value) + { + return this->insert( + BSLS_COMPILERFEATURES_FORWARD(LOOKUP_KEY, value)).first; + } +// }}} END GENERATED CODE + /// Insert into this set the value of each `value_type` object in the /// range starting at the specified `first` iterator and ending /// immediately before the specified `last` iterator, if a key @@ -474,29 +513,29 @@ class unordered_set { #ifndef BSLSTL_UNORDEREDSET_VARIADIC_LIMIT #define BSLSTL_UNORDEREDSET_VARIADIC_LIMIT 10 #endif -#ifndef BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A -#define BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A BSLSTL_UNORDEREDSET_VARIADIC_LIMIT +#ifndef BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C +#define BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C BSLSTL_UNORDEREDSET_VARIADIC_LIMIT #endif -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 0 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 0 pair emplace( ); -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 0 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 0 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 1 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 1 template pair emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 1 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 1 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 2 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 2 template pair emplace( BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 2 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 2 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 3 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 3 template @@ -504,9 +543,9 @@ class unordered_set { 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_UNORDEREDSET_VARIADIC_LIMIT_A >= 3 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 3 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 4 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 4 template = 4 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 4 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 5 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 5 template = 5 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 5 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 6 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 6 template = 6 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 6 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 7 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 7 template = 7 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 7 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 8 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 8 template = 8 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 8 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 9 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 9 template = 9 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 9 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 10 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 10 template = 10 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 10 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 0 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 0 iterator emplace_hint(const_iterator hint); -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 0 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 0 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 1 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 1 template iterator emplace_hint(const_iterator hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01); -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 1 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 1 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 2 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 2 template iterator emplace_hint(const_iterator hint, BSLS_COMPILERFEATURES_FORWARD_REF(Args_01) arguments_01, BSLS_COMPILERFEATURES_FORWARD_REF(Args_02) arguments_02); -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 2 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 2 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 3 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 3 template @@ -659,9 +698,9 @@ class unordered_set { 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_UNORDEREDSET_VARIADIC_LIMIT_A >= 3 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 3 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 4 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 4 template = 4 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 4 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 5 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 5 template = 5 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 5 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 6 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 6 template = 6 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 6 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 7 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 7 template = 7 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 7 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 8 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 8 template = 8 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 8 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 9 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 9 template = 9 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 9 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_A >= 10 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 10 template = 10 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_C >= 10 #else // The generated code below is a workaround for the absence of perfect @@ -861,6 +900,8 @@ class unordered_set { /// `key`, if such an entry exists, and the past-the-end (`end`) /// iterator otherwise. The behavior is undefined unless `key` is /// equivalent to at most one element in this unordered set. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -868,7 +909,6 @@ class unordered_set { iterator>::type find(const LOOKUP_KEY& key) { - // Note: implemented inline due to Sun CC compilation error. return iterator(d_impl.find(key)); } @@ -888,6 +928,8 @@ class unordered_set { /// undefined unless `key` is equivalent to at most one element in this /// unordered set. Note that since an unordered set maintains unique /// keys, the range will contain at most one element. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -895,7 +937,6 @@ class unordered_set { pair >::type equal_range(const LOOKUP_KEY& key) { - // Note: implemented inline due to Sun CC compilation error. typedef bsl::pair ResultType; HashTableLink *first = d_impl.find(key); @@ -969,6 +1010,8 @@ class unordered_set { /// Return `true` if this unordered set contains an element whose key is /// equivalent to the specified `key`. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value && @@ -977,7 +1020,6 @@ class unordered_set { bool>::type contains(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error return find(key) != end(); } @@ -1008,6 +1050,8 @@ class unordered_set { /// specified `key`, if such an entry exists, and the past-the-end /// (`end`) iterator otherwise. The behavior is undefined unless `key` /// is equivalent to at most one element in this unordered set. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1015,7 +1059,6 @@ class unordered_set { const_iterator>::type find(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error. return const_iterator(d_impl.find(key)); } @@ -1030,6 +1073,8 @@ class unordered_set { /// undefined unless `key` is equivalent to at most one element in this /// unordered set. Note that since an unordered set maintains unique /// keys, the returned value will be either 0 or 1. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1037,7 +1082,6 @@ class unordered_set { size_type>::type count(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error. return d_impl.find(key) != 0; } @@ -1057,6 +1101,8 @@ class unordered_set { /// undefined unless `key` is equivalent to at most one element in this /// unordered set. Note that since an unordered set maintains unique /// keys, the range will contain at most one element. + /// + /// Note: implemented inline due to Sun CC compilation error. template typename enable_if< BloombergLP::bslmf::IsTransparentPredicate::value @@ -1064,7 +1110,6 @@ class unordered_set { pair >::type equal_range(const LOOKUP_KEY& key) const { - // Note: implemented inline due to Sun CC compilation error. typedef bsl::pair ResultType; HashTableLink *first = d_impl.find(key); @@ -1822,10 +1867,10 @@ void unordered_set::clear() BSLS_KEYWORD_NOEXCEPT #ifndef BSLSTL_UNORDEREDSET_VARIADIC_LIMIT #define BSLSTL_UNORDEREDSET_VARIADIC_LIMIT 10 #endif -#ifndef BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B -#define BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B BSLSTL_UNORDEREDSET_VARIADIC_LIMIT +#ifndef BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D +#define BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D BSLSTL_UNORDEREDSET_VARIADIC_LIMIT #endif -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 0 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 0 template inline pair::iterator, bool> @@ -1841,9 +1886,9 @@ unordered_set::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 0 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 1 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 1 template template inline @@ -1861,9 +1906,9 @@ unordered_set::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 1 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 2 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 2 template template @@ -1884,9 +1929,9 @@ unordered_set::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 2 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 3 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 3 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 3 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 4 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 4 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 4 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 5 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 5 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 5 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 6 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 6 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 6 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 7 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 7 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 7 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 8 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 8 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 8 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 9 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 9 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 9 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 10 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 10 template template ::emplace( return ResultType(iterator(result), isInsertedFlag); } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 10 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 10 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 0 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 0 template inline typename unordered_set::iterator @@ -2189,9 +2234,9 @@ unordered_set::emplace_hint(const_iterator) return this->emplace().first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 0 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 0 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 1 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 1 template template inline @@ -2204,9 +2249,9 @@ unordered_set::emplace_hint(const_iterator, this->emplace(BSLS_COMPILERFEATURES_FORWARD(Args_01, arguments_01) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 1 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 1 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 2 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 2 template template @@ -2222,9 +2267,9 @@ unordered_set::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_02, arguments_02) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 2 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 2 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 3 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 3 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_03, arguments_03) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 3 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 3 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 4 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 4 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_04, arguments_04) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 4 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 4 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 5 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 5 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_05, arguments_05) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 5 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 5 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 6 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 6 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_06, arguments_06) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 6 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 6 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 7 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 7 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_07, arguments_07) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 7 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 7 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 8 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 8 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_08, arguments_08) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 8 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 8 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 9 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 9 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_09, arguments_09) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 9 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 9 -#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 10 +#if BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 10 template template ::emplace_hint(const_iterator, BSLS_COMPILERFEATURES_FORWARD(Args_10, arguments_10) ).first; } -#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_B >= 10 +#endif // BSLSTL_UNORDEREDSET_VARIADIC_LIMIT_D >= 10 #else // The generated code below is a workaround for the absence of perfect diff --git a/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp b/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp index b3c535b6cd..d98fb7c5b4 100644 --- a/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp +++ b/groups/bsl/bslstl/bslstl_unorderedset_test.t.cpp @@ -224,9 +224,11 @@ using bsls::NameOf; //*[23] TBD: Not yet working for all types. //*[ ] CONCERN: The type provides the full interface defined by the standard. // [33] CONCERN: Methods qualifed `noexcept` in standard are so implemented. -// [34] CONCERN: `find` properly handles transparent comparators. -// [34] CONCERN: `count` properly handles transparent comparators. -// [34] CONCERN: `equal_range` properly handles transparent comparators. +// [34] CONCERN: `find` properly handles t-parent comparators. +// [34] CONCERN: `count` properly handles t-parent comparators. +// [34] CONCERN: `equal_range` properly handles t-parent comparators. +// [34] CONCERN: `insert` properly handles t-parent comparators. +// [34] CONCERN: `insert_or_assign` properly handles t-parent comparators. // [35] CLASS TEMPLATE DEDUCTION GUIDES // [37] CONCERN: `unordered_set` IS A C++20 RANGE @@ -1463,6 +1465,9 @@ struct CompareProctor { class TransparentlyComparable { // DATA +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L + mutable +#endif int d_conversionCount; // number of times `operator int` has been called int d_value; // the value @@ -1484,11 +1489,21 @@ class TransparentlyComparable { /// Return the current value of this object. operator int() +#if BSLS_COMPILERFEATURES_CPLUSPLUS < 201103L + const +#endif { ++d_conversionCount; return d_value; } + /// return a count of the number of times this object has been converted to + /// an int. + void resetConversionCount() + { + d_conversionCount = 0; + } + // ACCESSORS /// Return the number of times `operator int` has been called. @@ -1570,125 +1585,214 @@ struct TransparentHasher /// `const`-qualified type, we are using the "reference" here as a sort of /// universal reference; conceptually, the object remains constant, but we /// want to test `const`-qualified and non-`const`-qualified overloads. -template -void testTransparentComparator(Container& container, - bool isTransparent, - int initKeyValue) +template +void testTransparentComparator(t_CONTAINER& container, + bool isTransparent, + int initKeyValue) { - typedef typename Container::const_local_iterator LocalIterator; - typedef typename Container::const_iterator Iterator; - typedef typename Container::size_type Count; + typedef typename t_CONTAINER::const_local_iterator LocalIterator; + typedef typename t_CONTAINER::const_iterator Iterator; + typedef typename t_CONTAINER::size_type Count; - int expectedConversionCount = 0; + const int expectedConversionCount = isTransparent ? 0 : 1; TransparentlyComparable existingKey(initKeyValue); TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue : -100); - ASSERT(existingKey.conversionCount() == expectedConversionCount); + { + // Testing `find`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `find`. + const Iterator EXISTING_F = container.find(existingKey); + ASSERT(container.end() != EXISTING_F); + ASSERT(existingKey.value() == *EXISTING_F); + ASSERT(existingKey.conversionCount() == expectedConversionCount); - const Iterator EXISTING_F = container.find(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const Iterator NON_EXISTING_F = container.find(nonExistingKey); + ASSERT(container.end() == NON_EXISTING_F); + ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); } - ASSERT(container.end() != EXISTING_F); - ASSERT(existingKey.value() == *EXISTING_F); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const Iterator NON_EXISTING_F = container.find(nonExistingKey); - ASSERT(container.end() == NON_EXISTING_F); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + { + // Testing `contains`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `contains`. + const bool EXISTING_CONTAINS = container.contains(existingKey); + ASSERT(true == EXISTING_CONTAINS); + ASSERT(existingKey.conversionCount() == expectedConversionCount); - const bool EXISTING_CONTAINS = container.contains(existingKey); - if (!isTransparent) { - ++expectedConversionCount; + const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); + ASSERT(false == NON_EXISTING_CONTAINS); + ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); } - ASSERT(true == EXISTING_CONTAINS); - ASSERT(existingKey.conversionCount() == expectedConversionCount); - - const bool NON_EXISTING_CONTAINS = container.contains(nonExistingKey); - ASSERT(false == NON_EXISTING_CONTAINS); - ASSERT(nonExistingKey.conversionCount() == expectedConversionCount); + { + // Testing `count`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - // Testing `count`. + const Count EXPECTED_C = 1; + const Count EXISTING_C = container.count(existingKey); - const Count EXPECTED_C = 1; - const Count EXISTING_C = container.count(existingKey); + ASSERT(EXPECTED_C == EXISTING_C); + ASSERT(expectedConversionCount == existingKey.conversionCount()); - if (!isTransparent) { - ++expectedConversionCount; + const Count NON_EXISTING_C = container.count(nonExistingKey); + ASSERT(0 == NON_EXISTING_C); + ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); } - ASSERT(EXPECTED_C == EXISTING_C); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - - const Count NON_EXISTING_C = container.count(nonExistingKey); - ASSERT(0 == NON_EXISTING_C); - ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); - - // Testing `equal_range`. + { + // Testing `equal_range`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - const bsl::pair EXISTING_ER = + const Count EXPECTED_C = 1; + const bsl::pair EXISTING_ER = container.equal_range(existingKey); - if (!isTransparent) { - ++expectedConversionCount; - } + ASSERT(expectedConversionCount == existingKey.conversionCount()); + ASSERT(EXPECTED_C == static_cast( + bsl::distance(EXISTING_ER.first, EXISTING_ER.second))); - ASSERT(expectedConversionCount == existingKey.conversionCount()); - ASSERT(EXPECTED_C == - static_cast(bsl::distance(EXISTING_ER.first, EXISTING_ER.second))); + for (Iterator it = EXISTING_ER.first; it != EXISTING_ER.second; ++it) { + ASSERT(existingKey.value() == *it); + } - for (Iterator it = EXISTING_ER.first; it != EXISTING_ER.second; ++it) { - ASSERT(existingKey.value() == *it); + const bsl::pair NON_EXISTING_ER = + container.equal_range(nonExistingKey); + ASSERT(NON_EXISTING_ER.first == NON_EXISTING_ER.second); + ASSERT(expectedConversionCount == nonExistingKey.conversionCount()); } - const bsl::pair NON_EXISTING_ER = - 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); + { + // Testing `bucket`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); - if (!isTransparent) { - ++expectedConversionCount; - } + const Count bucketFound = container.bucket(existingKey); - ASSERTV(expectedConversionCount, existingKey.conversionCount(), - expectedConversionCount == existingKey.conversionCount()); - ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), - expectedConversionCount == nonExistingKey.conversionCount()); + ASSERTV(expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); - // check that we found the right bucket - bool found_it; - const typename Container::key_equal c_eq = container.key_eq(); + // check that we found the right bucket + bool found_it; + const typename t_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; + 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); + + const Count bucketNotFound = container.bucket(nonExistingKey); + ASSERTV(expectedConversionCount, nonExistingKey.conversionCount(), + expectedConversionCount == nonExistingKey.conversionCount()); + + 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); + } - 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; - } +/// Search for a value equal to the specified `initKeyValue` in the +/// specified `container`, and count the number of conversions expected +/// based on the specified `isTransparent`. Unlike `testTransparentComparator` +/// above, this method tests methods that may modify the container, so we make +/// copies of the container. +template +void testTransparentComparatorMutable(const t_CONTAINER& container, + bool isTransparent, + int initKeyValue) +{ + typedef typename t_CONTAINER::size_type Count; + typedef typename t_CONTAINER::iterator Iterator; + + const int expectedConversionCount = isTransparent ? 0 : 1; + + TransparentlyComparable existingKey(initKeyValue); + TransparentlyComparable nonExistingKey(initKeyValue ? -initKeyValue + : -100); + + { + // Testing `insert(value)`. + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + bsl::pair ret; + const Count size = c.size(); + + // with an existing key + ret = c.insert(existingKey); + ASSERT(!ret.second); + ASSERT(existingKey.value() == *ret.first); + ASSERT(size == c.size()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + ret = c.insert(nonExistingKey); + ASSERT(ret.second); + ASSERT(size + 1 == c.size()); + ASSERT(nonExistingKey.value() == *ret.first); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); + } + + // Testing `insert(hint, value)`. + { + existingKey.resetConversionCount(); + nonExistingKey.resetConversionCount(); + + t_CONTAINER c(container); + Iterator ret; + const Count size = c.size(); + + // with an existing key + ret = c.insert(c.begin(), existingKey); + ASSERT(existingKey.value() == *ret); + ASSERT(size == c.size()); + ASSERTV(isTransparent, + expectedConversionCount, existingKey.conversionCount(), + expectedConversionCount == existingKey.conversionCount()); + + // with a non-existing key + + // Note: We always get a conversion here; if we don't have a + // transparent comparator, then the value gets converted, and when the + // lookup fails, it gets inserted into the map. If we do have a + // transparent comparator, the lookup is done w/o conversion, but then + // the value gets converted in order to put it into the map. + ret = c.insert(c.begin(), nonExistingKey); + ASSERT(nonExistingKey.value() == *ret); + ASSERT(size + 1 == c.size()); + ASSERTV(isTransparent, + 1, nonExistingKey.conversionCount(), + 1 == nonExistingKey.conversionCount()); } - ASSERT(!found_it); } } // close unnamed namespace @@ -8709,9 +8813,11 @@ int main(int argc, char *argv[]) // no conversions. (C-2) // // Testing: - // CONCERN: `find` properly handles transparent comparators - // CONCERN: `count` properly handles transparent comparators - // CONCERN: `equal_range` properly handles transparent comparators + // CONCERN: `find` properly handles t-parent comparators + // CONCERN: `count` properly handles t-parent comparators + // CONCERN: `equal_range` properly handles t-parent comparators + // CONCERN: `insert` properly handles t-parent comparators + // CONCERN: `insert_or_assign` properly handles t-parent comparators // -------------------------------------------------------------------- if (verbose) printf("\n" "TESTING TRANSPARENT COMPARATOR" "\n" @@ -8755,8 +8861,8 @@ int main(int argc, char *argv[]) if (veryVerbose) { printf("\tTesting mutable non-transparent set.\n"); } - testTransparentComparator(mXNT, false, KEY); - + testTransparentComparator (mXNT, false, KEY); + testTransparentComparatorMutable(mXNT, false, KEY); if (veryVerbose) { printf("\tTesting const transparent set.\n"); } @@ -8765,7 +8871,8 @@ int main(int argc, char *argv[]) if (veryVerbose) { printf("\tTesting mutable transparent set.\n"); } - testTransparentComparator(mXT, true, KEY); + testTransparentComparator (mXT, true, KEY); + testTransparentComparatorMutable(mXT, true, KEY); } } break; case 33: {