// bslstl_mapcomparator.h -*-C++-*- #ifndef INCLUDED_BSLSTL_MAPCOMPARATOR #define INCLUDED_BSLSTL_MAPCOMPARATOR #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a comparator for 'TreeNode' objects and a lookup key. // //@CLASSES: // bslstl::MapComparator: comparator for 'TreeNode' objects and key objects // //@SEE_ALSO: bslstl_map, bslstl_treenode, bslalg_rbtreeutil // //@DESCRIPTION: This component provides a functor adapter, 'MapComparator', // that adapts a parameterized 'COMPARATOR' comparing objects of a // parameterized 'KEY' type into a functor comparing a object of 'KEY' type // with objects of 'TreeNode' type holding a 'bsl::pair<KEY, VALUE>' object. // Note that this functor was designed to be supplied to functions in // 'bslalg::RbTreeUtil', primarily for the purpose of implementing a 'map' // container using the utilities defined in 'bslalg::RbTreeUtil'. // ///Usage ///----- // This section illustrates intended use of this component. // ///Example 1: Create a Simple Tree of 'TreeNode' Objects ///- - - - - - - - - - - - - - - - - - - - - - - - - - - // Suppose that we want to create a tree of 'TreeNode' objects arranged // according to a functor that we supply. // // First, we create an array of 'bslstl::TreeNode' objects, each holding a pair // of integers: //.. // typedef bsl::allocator<TreeNode<bsl::pair<int, int> > > Alloc; // // bslma::TestAllocator oa; // Alloc allocator(&oa); // // enum { NUM_NODES = 5 }; // // bslstl::TreeNode<bsl::pair<int, int> >* nodes[NUM_NODES]; // // typedef bsl::allocator_traits<Alloc> AllocTraits; // // for (int i = 0; i < NUM_NODES; ++i) { // nodes[i] = AllocTraits::allocate(allocator, 1); // AllocTraits::construct(allocator, &nodes[i]->value(), // i, 2*i); // } //.. // Then, we define a 'MapComparator' object, 'comparator', for comparing // 'bslstl::TreeNode<pair<int, int> >' objects with integers. //.. // MapComparator<int, int, std::less<int> > comparator; //.. // Now, we can use the functions in 'bslalg::RbTreeUtil' to arrange our tree: //.. // bslalg::RbTreeAnchor tree; // // for (int i = 0; i < NUM_NODES; ++i) { // int comparisonResult; // bslalg::RbTreeNode *insertLocation = // bslalg::RbTreeUtil::findUniqueInsertLocation( // &comparisonResult, // &tree, // comparator, // nodes[i]->value().first); // // assert(0 != comparisonResult); // // bslalg::RbTreeUtil::insertAt(&tree, // insertLocation, // comparisonResult < 0, // nodes[i]); // } // // assert(5 == tree.numNodes()); //.. // Then, we use 'bslalg::RbTreeUtil::next()' to navigate the elements of the // tree, printing their values: //.. // const bslalg::RbTreeNode *nodeIterator = tree.firstNode(); // // while (nodeIterator != tree.sentinel()) { // const TreeNode<bsl::pair<int, int> > *node = // static_cast<const TreeNode<bsl::pair<int, int> >*>(nodeIterator); // printf("Node value: (%d, %d)\n", // node->value().first, node->value().second); // nodeIterator = bslalg::RbTreeUtil::next(nodeIterator); // } //.. // Next, we destroy and deallocate each of the 'bslstl::TreeNode' objects: //.. // for (int i = 0; i < NUM_NODES; ++i) { // AllocTraits::destroy(allocator, &nodes[i]->value()); // AllocTraits::deallocate(allocator, nodes[i], 1); // } //.. // Finally, we observe the console output: //.. // Node value: (0, 0) // Node value: (1, 2) // Node value: (2, 4) // Node value: (3, 6) // Node value: (4, 8) //.. #include <bslscm_version.h> #include <bslstl_pair.h> #include <bslstl_treenode.h> #include <bslalg_functoradapter.h> #include <bslalg_swaputil.h> #include <bsls_platform.h> #include <bsls_util.h> namespace BloombergLP { namespace bslstl { // =================== // class MapComparator // =================== template <class KEY, class VALUE, class COMPARATOR> #ifdef BSLS_PLATFORM_CMP_MSVC // Visual studio compiler fails to resolve the conversion operator in // 'bslalg::FunctorAdapter_FunctionPointer' when using private inheritance. // Below is a workaround until a more suitable way the resolve this issue can // be found. class MapComparator : public bslalg::FunctorAdapter<COMPARATOR>::Type { #else class MapComparator : private bslalg::FunctorAdapter<COMPARATOR>::Type { #endif // This class overloads the function-call operator to compare a referenced // 'bslalg::RbTreeNode' object with a object of the parameterized 'KEY' // type, assuming the reference to 'bslalg::RbTreeNode' is a base of a // 'bslstl::TreeNode' holding a 'pair<KEY, VALUE>', using a functor of the // parameterized 'COMPARATOR' type. private: // This class does not support assignment. MapComparator& operator=(const MapComparator&); // Declared but not // defined public: // TYPES typedef bsl::pair<const KEY, VALUE> ValueType; // This alias represents the type of the values held by nodes in an // 'bslalg::RbTree' object. typedef TreeNode<ValueType> NodeType; // This alias represents the type of node holding a 'ValueType' object. // CREATORS MapComparator(); // Create a 'MapComparator' object that will use a default constructed // 'COMPARATOR'. explicit MapComparator(const COMPARATOR& keyComparator); // Create a 'MapComparator' object holding a copy of the specified // 'keyComparator'. //! MapComparator(const MapComparator& original) = default; // Create a 'MapComparator' object with the 'COMPARATOR' object of the // specified 'original' object. //! ~MapComparator() = default; // Destroy this object. // MANIPULATORS template <class LOOKUP_KEY> bool operator()(const LOOKUP_KEY& lhs, const bslalg::RbTreeNode& rhs); // Return 'true' if the specified 'lhs' is less than (ordered before, // according to the comparator held by this object) 'value().first' of // the specified 'rhs' after being cast to 'NodeType', and 'false' // otherwise. The behavior is undefined unless 'rhs' can be safely // cast to 'NodeType'. template <class LOOKUP_KEY> bool operator()(const bslalg::RbTreeNode& lhs, const LOOKUP_KEY& rhs); // Return 'true' if 'value().first()' of the specified 'lhs' after // being cast to 'NodeType' is less than (ordered before, according to // the comparator held by this object) the specified 'rhs', and 'false' // otherwise. The behavior is undefined unless 'rhs' can be safely // cast to 'NodeType'. void swap(MapComparator& other); // Efficiently exchange the value of this object with the value of the // specified 'other' object. This method provides the no-throw // exception-safety guarantee. // ACCESSORS template <class LOOKUP_KEY> bool operator()(const LOOKUP_KEY& lhs, const bslalg::RbTreeNode& rhs) const; // Return 'true' if the specified 'lhs' is less than (ordered before, // according to the comparator held by this object) 'value().first' of // the specified 'rhs' after being cast to 'NodeType', and 'false' // otherwise. The behavior is undefined unless 'rhs' can be safely // cast to 'NodeType'. template <class LOOKUP_KEY> bool operator()(const bslalg::RbTreeNode& lhs, const LOOKUP_KEY& rhs) const; // Return 'true' if 'value().first()' of the specified 'lhs' after // being cast to 'NodeType' is less than (ordered before, according to // the comparator held by this object) the specified 'rhs', and 'false' // otherwise. The behavior is undefined unless 'rhs' can be safely // cast to 'NodeType'. COMPARATOR& keyComparator(); // Return a reference providing modifiable access to the function // pointer or functor to which this comparator delegates comparison // operations. const COMPARATOR& keyComparator() const; // Return a reference providing non-modifiable access to the function // pointer or functor to which this comparator delegates comparison // operations. }; // FREE FUNCTIONS template <class KEY, class VALUE, class COMPARATOR> void swap(MapComparator<KEY, VALUE, COMPARATOR>& a, MapComparator<KEY, VALUE, COMPARATOR>& b); // Efficiently exchange the values of the specified 'a' and 'b' objects. // This function provides the no-throw exception-safety guarantee. // ============================================================================ // TEMPLATE AND INLINE FUNCTION DEFINITIONS // ============================================================================ // ------------------- // class MapComparator // ------------------- // CREATORS template <class KEY, class VALUE, class COMPARATOR> inline MapComparator<KEY, VALUE, COMPARATOR>::MapComparator() : bslalg::FunctorAdapter<COMPARATOR>::Type() { } template <class KEY, class VALUE, class COMPARATOR> inline MapComparator<KEY, VALUE, COMPARATOR>:: MapComparator(const COMPARATOR& valueComparator) : bslalg::FunctorAdapter<COMPARATOR>::Type(valueComparator) { } // MANIPULATORS template <class KEY, class VALUE, class COMPARATOR> inline void MapComparator<KEY, VALUE, COMPARATOR>::swap( MapComparator<KEY, VALUE, COMPARATOR>& other) { bslalg::SwapUtil::swap( static_cast<typename bslalg::FunctorAdapter<COMPARATOR>::Type*>(this), static_cast<typename bslalg::FunctorAdapter<COMPARATOR>::Type*>( BSLS_UTIL_ADDRESSOF(other))); } // ACCESSOR template <class KEY, class VALUE, class COMPARATOR> template <class LOOKUP_KEY> inline bool MapComparator<KEY, VALUE, COMPARATOR>::operator()( const LOOKUP_KEY& lhs, const bslalg::RbTreeNode& rhs) { return keyComparator()(lhs, static_cast<const NodeType&>(rhs).value().first); } template <class KEY, class VALUE, class COMPARATOR> template <class LOOKUP_KEY> inline bool MapComparator<KEY, VALUE, COMPARATOR>::operator()( const LOOKUP_KEY& lhs, const bslalg::RbTreeNode& rhs) const { return keyComparator()(lhs, static_cast<const NodeType&>(rhs).value().first); } template <class KEY, class VALUE, class COMPARATOR> template <class LOOKUP_KEY> inline bool MapComparator<KEY, VALUE, COMPARATOR>::operator()( const bslalg::RbTreeNode& lhs, const LOOKUP_KEY& rhs) { return keyComparator()(static_cast<const NodeType&>(lhs).value().first, rhs); } template <class KEY, class VALUE, class COMPARATOR> template <class LOOKUP_KEY> inline bool MapComparator<KEY, VALUE, COMPARATOR>::operator()( const bslalg::RbTreeNode& lhs, const LOOKUP_KEY& rhs) const { return keyComparator()(static_cast<const NodeType&>(lhs).value().first, rhs); } template <class KEY, class VALUE, class COMPARATOR> inline COMPARATOR& MapComparator<KEY, VALUE, COMPARATOR>::keyComparator() { return *this; } template <class KEY, class VALUE, class COMPARATOR> inline const COMPARATOR& MapComparator<KEY, VALUE, COMPARATOR>::keyComparator() const { return *this; } // FREE FUNCTIONS template <class KEY, class VALUE, class COMPARATOR> void swap(MapComparator<KEY, VALUE, COMPARATOR>& a, MapComparator<KEY, VALUE, COMPARATOR>& b) { a.swap(b); } } // close package namespace } // close enterprise namespace #endif // ---------------------------------------------------------------------------- // Copyright 2013 Bloomberg Finance L.P. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ----------------------------- END-OF-FILE ----------------------------------