The Traversable Interfaces
Exchanging a collection between classes or functions usually requires an agreed-upon collection type. For example, perhaps you need to write a display_employees() function that takes a collection of employees and writes their names to a console. With STL, you might write the function as in Displaying a collection with standard STL iteration.
Displaying a collection with standard STL iteration
void display_employees( const vector< employee >& vEmpl )
{
vector< employee >::const_iterator i;
// Traverse and process the items
for (i = vEmpl.begin(); i != vEmpl.end(); i++) {
cout << (*i).GetName();
}
}
But, what if the employees are sometimes stored in a map or a list? You would have to write this function three or more times, only changing the collection type. You can use templated functions to accomplish this, but they are still generating essentially the same function three or more times.
With polymorphic iteration, you can write one function to process an aggregate, regardless of the collection type. The Stingray Foundation Library defines two interface templates for this purpose:
All polymorphic iterators take one of these interfaces as a constructor argument, and use it as a bridge to the collection. The iterator calls the traversal interface members to move between and access elements. Any collection that implements these interfaces becomes accessible through the polymorphic iterators.
With IConstTraversableT<>, you can rewrite the display_employees() function once for all collection types, as shown in Displaying all collection types with SFL polymorphic iteration.
Displaying all collection types with SFL polymorphic iteration
void display_employees( IConstTraversableT< employee >& tEmpl )
{
const_iterator< employee > i(tEmpl);
/*** Next line doesn’t compile
iterator< employee > i(tEmpl);
**** only const iterators allowed
**** on an IConstTraversableT<> */
// Traverse and process the items
for (i.begin(); !i.at_end(); i++) {
cout << (*i).GetName();
}
}
Both IConstTraversableT<> and ITraversableT<> serve as abstract aggregate objects that can be iterated over. The difference is that IConstTraversableT<> supports only const_iterator<> and const_reverse_iterator<>, while ITraversableT<> supports all four polymorphic iterator types.
The power of traversable interfaces is that they allow you to exchange and use aggregates without concern for collection type. Returning a collection is another place where this is useful, as shown in Using aggregates without knowing collection type, where a function searches for all employees contributing to a 401K plan.
Using aggregates without knowing collection type
ITraversableT< employee >& EmployeeServer::Get401kContributors()
{
// Perform SQL query
...
return m_tMatches;
}
Now, client code will be able to receive, traverse and process the returned set of employees, without knowing the collection type or impacting the code when the type changes.






