Most of the Tools.h++ collection class templates use the Standard C++ Library for their underlying implementation. The collection classes of the Standard C++ Library, called containers, act as an engine under the hood of the Tools.h++ templates.
For example, the value-based Tools.h++ double-ended queue RWTValDeque<T> has-a member of type deque<T> from the Standard C++ Library. This member serves as the implementation of the collection. Like an engine, it does the bulk of the work of adding and removing elements, and so on. RWTValDeque<T> is a wrapper class, like the hood protecting the engine. More than cosmetic, it functions as a simpler, object-oriented interface to the deque class, making it easier and more pleasant to deal with.
Thanks to inlining and the lack of any extra level of indirection, this wrapping incurs few, if any, performance penalties. If you need direct access to the implementation, the wrapper classes offer the member function std(), which returns a reference to the implementation. In addition, because the Rogue Wave template collections supply standard iterators, you can use them with the Standard C++ Library algorithms as if they were Standard C++ Library collections themselves.
A unique feature of this version of Tools.h++ is that many of its template collections do not actually require the presence of the Standard C++ Library. Consider RWTValDlist<T>. If you are using Tools.h++ on a platform that supports the Standard C++ Library, RWTValDlist<T> will be built around the Standard C++ Library list container. But if your platform does not support the Standard C++ Library, you may still use the class. Tools.h++ accomplishes this feat transparently through an alternate implementation, not based on the Standard C++ Library. The appropriate implementation is selected at compile time based on the settings in the configuration header file, rw/compiler.h. In fact, the alternate implementations are exactly those that were employed in the previous version of Tools.h++.
When using one of these template collections without the Standard C++ Library, you will be restricted to a subset of the full interface. For example, the std() member function mentioned above is not available, nor are the begin() and end() functions, which return Standard C++ Library iterators. The Tools.h++ Class Reference contains entries for both the full and the subset interfaces for all of the templates that can be used either with or without the Standard C++ Library.
There are two reasons you may want to use the restricted subset interface for a collection class template:
You may be operating in an environment that does not yet support a version of the Standard C++ Library compatible with this version of Tools.h++. In that case, you have no choice but to use the restricted subset interface. The good news is that by using the interface, you will be ready to start using the full interface as soon as the Standard C++ Library becomes available on your platform.
Another reason to stick to the subset interface is that you want to write portable code -- a class library, perhaps -- that can be deployed on multiple platforms, some without support for the Standard C++ Library. Clients of that code can still take full advantage of their individual environments; you aren't forced to inflict on them a "lowest common denominator." See Section 2.10 toward the end of this chapter for more information on the restricted subset interface.
There are seven Standard C++ Library containers: deque, list, vector, set, multiset, map, and multimap. Tools.h++ extends these with five additional containers which are compliant with the Standard C++ Library: rw_slist, rw_hashset, rw_hashmultiset, rw_hashmap, and rw_hashmultimap. Each of these has value-based and pointer-based Rogue Wave wrapper templates. Tools.h++ also offers always-sorted versions, both value-based and pointer-based, of the doubly-linked list and vector collections. The total: 28 new or re-engineered collection class templates, all based on the Standard C++ Library!
Tools.h++ Standard Library-Based Templates |
|||
Division // Notes |
Value-based |
Pointer-based |
Standard Library
Required? |
Sequence-based //External ordering, access by index |
RWTValDlist |
RWTPtrDlist |
No |
RWTValDeque |
RWTPtrDeque |
Yes |
|
RWTValOrderedVector |
RWTPtrOrderedVector |
No |
|
RWTValSlist |
RWTPtrSlist |
No |
|
Sorted sequence-based //Internal ordering, access by index |
RWTValSortedDlist |
RWTPtrSortedDlist |
Yes |
RWTValSortedVector |
RWTPtrSortedVector |
No |
|
Associative container-based //Internal ordering, access by key |
RWTValSet |
RWTPtrSet |
Yes |
(set-based) |
RWTValMutliSet |
RWTPtrMultiSet |
Yes |
(map-based) |
RWTValMap |
RWTPtrMap |
Yes |
RWTValMultiMap |
RWTPtrMultiMap |
Yes |
|
Associative hash -based //No ordering, access by key |
RWTValHashSet |
RWTPtrHashSet |
No |
(set-based) |
RWTValHashMutliSet |
RWTPtrHashMultiSet |
No |
(map-based) |
RWTValHashMap |
RWTPtrHashMap |
No |
RWTValHashMultiMap |
RWTPtrHashMultiMap |
Yes |
To keep things simple and allow you to program with more flexibility, we have implemented common interfaces within the various divisions of standard-library based collection class templates. For example, the RWTPtrSet and RWTPtrMultiSet templates have interfaces identical to their value-based cousins; so do the map-based collection classes. All of the Sequence-based collections have nearly identical interfaces within the value and pointer-based subgroups. (An exception here is the set of deque-based classes, which contain push and pop member functions designed to enhance their abstraction of the queue data structure.)
There are pluses and minuses to this approach. The downside is that it puts slightly more of the burden on you, the developer, to choose the appropriate collection class. Had we chosen not to provide the insertAt(size_type index) member function for class RWTValOrderedVector<Type>, we could have enforced the idea that vector-based templates are not a good choice for inserting into the middle of a collection class. Instead, it is up to you to be aware of your choices and use such member functions judiciously.
On the plus side, the common interface lowers the learning curve, allows flexibility in experimenting with different collections, and provides the capability of dealing with the Rogue Wave templates polymorphically via genericity.[14]
Real-life programming is seldom as neat as the exercises in a data structures textbook. You may find yourself in a situation where it is difficult to balance the trade-offs and determine just which collection class to use. With the common interface, you can easily benchmark code that uses an RWTValDeque and later benchmark it again, substituting an RWTValOrderedVector or RWTValDlist. You can also write class and function templates that are parameterized on the collection class type. For example:
template <class RWSeqBased> void tossHiLo(RWSeqBased& coll) { // throw out the high and low values: assert(coll.entries() >= 2); // precondition coll.sort(); coll.removeFirst(); coll.removeLast(); }
Thanks to the common interface, the above function template will work when instantiated with any of the Rogue Wave Sequence-based templates.