// bslstl_treenode.h -*-C++-*- #ifndef INCLUDED_BSLSTL_TREENODE #define INCLUDED_BSLSTL_TREENODE #include <bsls_ident.h> BSLS_IDENT("$Id: $") //@PURPOSE: Provide a POD-like tree node type holding a parameterized value. // //@CLASSES: // bslstl::TreeNode: a tree node holding a parameterized value // //@SEE_ALSO: bslstl_treenodefactory, bslstl_set, bslstl_map // //@DESCRIPTION: This component provides a single POD-like class, 'TreeNode', // used to represent a node in a red-black binary search tree holding a value // of a parameterized type. A 'TreeNode' inherits from 'bslalg::RbTreeNode', // so it may be used with 'bslalg::RbTreeUtil' functions, and adds an attribute // 'value' of the parameterized 'VALUE'. The following inheritance hierarchy // diagram shows the classes involved and their methods: //.. // ,----------------. // ( bslstl::TreeNode ) // `----------------' // | value // V // ,------------------. // ( bslalg::RbTreeNode ) // `------------------' // ctor // dtor // makeBlack // makeRed // setParent // setLeftChild // setRightChild // setColor // toggleColor // parent // leftChild // rightChild // isBlack // isRed // color //.. // This class is "POD-like" to facilitate efficient allocation and use in the // context of a container implementation. In order to meet the essential // requirements of a POD type, both this 'class' and 'bslalg::RbTreeNode' do // not define a constructor or destructor. The manipulator, 'value', returns a // modifiable reference to the object that may be constructed in-place by the // appropriate 'bsl::allocator_traits' object. // ///Usage ///----- // In this section we show intended usage of this component. // ///Example 1: Allocating and Deallocating 'TreeNode' Objects. /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In the following example we define a factory class for allocating and // destroying 'TreeNode' objects. // // First, we define the interface for the class 'NodeFactory': //.. // template <class VALUE, class ALLOCATOR> // class NodeFactory { //.. // The parameterized 'ALLOCATOR' is intended to allocate objects of the // parameterized 'VALUE', so to use it to allocate objects of 'TreeNode<VALUE>' // we must rebind it to the tree node type. Note that in general, we use // 'allocator_traits' to perform actions using an allocator (including the // rebind below): //.. // // PRIVATE TYPES // typedef typename bsl::allocator_traits<ALLOCATOR>::template // rebind_traits<TreeNode<VALUE> > AllocatorTraits; // typedef typename AllocatorTraits::allocator_type NodeAllocator; // // // DATA // NodeAllocator d_allocator; // rebound tree-node allocator // // // NOT IMPLEMENTED // NodeFactory(const NodeFactory&); // NodeFactory& operator=(const NodeFactory&); // // public: // // CREATORS // NodeFactory(const ALLOCATOR& allocator); // // Create a tree node-factory that will use the specified // // 'allocator' to supply memory. // // // MANIPULATORS // TreeNode<VALUE> *createNode(const VALUE& value); // // Create a new 'TreeNode' object holding the specified 'value'. // // void deleteNode(bslalg::RbTreeNode *node); // // Destroy and deallocate the specified 'node'. The behavior is // // undefined unless 'node' is the address of a // // 'TreeNode<VALUE>' object. // }; //.. // Now, we implement the 'NodeFactory' type: //.. // template <class VALUE, class ALLOCATOR> // inline // NodeFactory<VALUE, ALLOCATOR>::NodeFactory(const ALLOCATOR& allocator) // : d_allocator(allocator) // { // } //.. // We implement the 'createNode' function by using the rebound // 'allocator_traits' for our allocator to in-place copy-construct the // supplied 'value' into the 'value' data member of our 'result' node // object. Note that 'TreeNode' is a POD-like type, without a constructor, so // we do not need to call its constructor here: //.. // template <class VALUE, class ALLOCATOR> // inline // TreeNode<VALUE> * // NodeFactory<VALUE, ALLOCATOR>::createNode(const VALUE& value) // { // TreeNode<VALUE> *result = AllocatorTraits::allocate(d_allocator, 1); // AllocatorTraits::construct(d_allocator, // bsls::Util::addressOf(result->value()), // value); // return result; // } //.. // Finally, we implement the function 'deleteNode'. Again, we use the // rebound 'allocator_traits' for our tree node type, this time to destroy the // 'value' date member of node, and then to deallocate its footprint. Note // that 'TreeNode' is a POD-like type, so we do not need to call its destructor // here: //.. // template <class VALUE, class ALLOCATOR> // inline // void NodeFactory<VALUE, ALLOCATOR>::deleteNode(bslalg::RbTreeNode *node) // { // TreeNode<VALUE> *treeNode = static_cast<TreeNode<VALUE> *>(node); // AllocatorTraits::destroy(d_allocator, // bsls::Util::addressOf(treeNode->value())); // AllocatorTraits::deallocate(d_allocator, treeNode, 1); // } //.. // ///Example 2: Creating a Simple Tree of 'TreeNode' Objects. /// - - - - - - - - - - - - - - - - - - - - - - - - - - - - // In the following example we create a container-type 'Set' for // holding a set of values of a parameterized 'VALUE'. // // First, we define a comparator for 'VALUE' of 'TreeNode<VALUE>' objects. // This type is designed to be supplied to functions in 'bslalg::RbTreeUtil'. // Note that, for simplicity, this type uses 'operator<' to compare values, // rather than a client defined comparator type. //.. // template <class VALUE> // class Comparator { // public: // // CREATORS // Comparator() {} // // Create a node-value comparator. // // // ACCESSORS // bool operator()(const VALUE& lhs, // const bslalg::RbTreeNode& rhs) const; // bool operator()(const bslalg::RbTreeNode& lhs, // const VALUE& rhs) const; // // Return 'true' if the specified 'lhs' is less than (ordered // // before) the specified 'rhs', and 'false' otherwise. The // // behavior is undefined unless the supplied 'bslalg::RbTreeNode' // // object is of the derived 'TreeNode<VALUE>' type. // }; //.. // Then, we implement the comparison methods of 'Comparator'. Note that the // supplied 'RbTreeNode' objects must be 'static_cast' to // 'TreeNode<VALUE>' to access their value: //.. // template <class VALUE> // inline // bool Comparator<VALUE>::operator()(const VALUE& lhs, // const bslalg::RbTreeNode& rhs) const // { // return lhs < static_cast<const TreeNode<VALUE>& >(rhs).value(); // } // // template <class VALUE> // inline // bool Comparator<VALUE>::operator()(const bslalg::RbTreeNode& lhs, // const VALUE& rhs) const // { // return static_cast<const TreeNode<VALUE>& >(lhs).value() < rhs; // } //.. // Now, having defined the requisite helper types, we define the public // interface for 'Set'. Note that for the purposes of illustrating the use of // 'TreeNode' a number of simplifications have been made. For example, this // implementation provides only 'insert', 'remove', 'isMember', and // 'numMembers' operations: //.. // template <class VALUE, // class ALLOCATOR = bsl::allocator<VALUE> > // class Set { // // PRIVATE TYPES // typedef Comparator<VALUE> ValueComparator; // typedef NodeFactory<VALUE, ALLOCATOR> Factory; // // // DATA // bslalg::RbTreeAnchor d_tree; // tree of node objects // Factory d_factory; // allocator for node objects // // // NOT IMPLEMENTED // Set(const Set&); // Set& operator=(const Set&); // // public: // // CREATORS // Set(const ALLOCATOR& allocator = ALLOCATOR()); // // Create an empty set. Optionally specify a 'allocator' used to // // supply memory. If 'allocator' is not specified, a default // // constructed 'ALLOCATOR' object is used. // // ~Set(); // // Destroy this set. // // // MANIPULATORS // void insert(const VALUE& value); // // Insert the specified value into this set. // // bool remove(const VALUE& value); // // If 'value' is a member of this set, then remove it and return // // 'true', and return 'false' otherwise. // // // ACCESSORS // bool isElement(const VALUE& value) const; // // Return 'true' if the specified 'value' is a member of this set, // // and 'false' otherwise. // // int numElements() const; // // Return the number of elements in this set. // }; //.. // Now, we define the implementation of 'Set': //.. // // CREATORS // template <class VALUE, class ALLOCATOR> // inline // Set<VALUE, ALLOCATOR>::Set(const ALLOCATOR& allocator) // : d_tree() // , d_factory(allocator) // { // } // // template <class VALUE, class ALLOCATOR> // inline // Set<VALUE, ALLOCATOR>::~Set() // { // bslalg::RbTreeUtil::deleteTree(&d_tree, &d_factory); // } // // // MANIPULATORS // template <class VALUE, class ALLOCATOR> // void Set<VALUE, ALLOCATOR>::insert(const VALUE& value) // { // int comparisonResult; // ValueComparator comparator; // bslalg::RbTreeNode *parent = // bslalg::RbTreeUtil::findUniqueInsertLocation(&comparisonResult, // &d_tree, // comparator, // value); // if (0 != comparisonResult) { // bslalg::RbTreeNode *node = d_factory.createNode(value); // bslalg::RbTreeUtil::insertAt(&d_tree, // parent, // comparisonResult < 0, // node); // } // } // // template <class VALUE, class ALLOCATOR> // bool Set<VALUE, ALLOCATOR>::remove(const VALUE& value) // { // bslalg::RbTreeNode *node = // bslalg::RbTreeUtil::find(d_tree, ValueComparator(), value); // if (node) { // bslalg::RbTreeUtil::remove(&d_tree, node); // d_factory.deleteNode(node); // } // return node; // } // // // ACCESSORS // template <class VALUE, class ALLOCATOR> // inline // bool Set<VALUE, ALLOCATOR>::isElement(const VALUE& value) const // { // ValueComparator comparator; // return bslalg::RbTreeUtil::find(d_tree, comparator, value); // } // // template <class VALUE, class ALLOCATOR> // inline // int Set<VALUE, ALLOCATOR>::numElements() const // { // return d_tree.numNodes(); // } //.. // Notice that the definition and implementation of 'Set' never directly // uses the 'TreeNode' type, but instead use it indirectly through // 'Comparator', and 'NodeFactory', and uses it via its base-class // 'bslalg::RbTreeNode'. // // Finally, we test our 'Set'. //.. // Set<int> set; // assert(0 == set.numElements()); // // set.insert(1); // assert(set.isElement(1)); // assert(1 == set.numElements()); // // set.insert(1); // assert(set.isElement(1)); // assert(1 == set.numElements()); // // set.insert(2); // assert(set.isElement(1)); // assert(set.isElement(2)); // assert(2 == set.numElements()); //.. #include <bslalg_rbtreenode.h> namespace BloombergLP { namespace bslstl { // ============== // class TreeNode // ============== template <class VALUE> class TreeNode : public bslalg::RbTreeNode { // This POD-like 'class' describes a node suitable for use in a red-black // binary search tree of values of the parameterized 'VALUE'. This class // is a "POD-like" to facilitate efficient allocation and use in the // context of a container implementation. In order to meet the essential // requirements of a POD type, this 'class' does not define a constructor // or destructor. The manipulator, 'value', returns a modifiable reference // to 'd_value' so that it may be constructed in-place by the appropriate // 'bsl::allocator_traits' object. // DATA VALUE d_value; // payload value private: // The following functions are not defined because a 'TreeNode' should // never be constructed, destructed, or assigned. The 'd_value' member // should be separately constructed and destroyed using an appropriate // 'bsl::allocator_traits' object. TreeNode(); // Declared but not defined TreeNode(const TreeNode&); // Declared but not defined TreeNode& operator=(const TreeNode&); // Declared but not defined ~TreeNode(); // Declared but not defined public: // MANIPULATORS VALUE& value(); // Return a reference providing modifiable access to the 'value' of // this object. // ACCESSORS const VALUE& value() const; // Return a reference providing non-modifiable access to the 'value' of // this object. }; // ============================================================================ // TEMPLATE AND INLINE FUNCTION DEFINITIONS // ============================================================================ template <class VALUE> inline VALUE& TreeNode<VALUE>::value() { return d_value; } template <class VALUE> inline const VALUE& TreeNode<VALUE>::value() const { return d_value; } } // 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 ----------------------------------