"Ed" <ed********@gmail.com> wrote in message
news:11**********************@o13g2000cwo.googlegr oups.com...
Hi,
I have a WorkUnit class. I will pass a reference to a group of these
WorkUnits to other classes in my application. I have chosen to use a
vector to hold pointers to these WorkUnits for now.
However, I think that I should hide the fact that it's a vector in case
I want to switch to another container class at a later date. I don't
want every class that needs to use the group of WorkUnits to be too
tightly bound to the details of the vector.
Is there a best practice for hiding the container implementation in
this case?
I can't say it's best practice, but I use the Visitor Pattern to hide the
container implementation where needed. For example(untested):
class Item
{
...
void Fnc(){ }
};
class GroupOfItems
{
public:
...
struct ItemVisitor
{
virtual ~ItemVisitor(){}
virtual void operator()( Item& )const{}
};
void ForEachItem( const ItemVisitor& );
};
void GroupOfItems::ForEachItem( const ItemVisitor& aItemVisitor )
{
std::for_each( c.begin(), c.end(), aItemVisitor );
}
used like:
void someFnc( GroupOfItems& aItems )
{
struct MyItemVisitor : public ItemVisitor
{
void operator()( Item& aItem )const{ aItem.Fnc(); }
};
aItems.ForEachItem( MyItemVisitor() );
}
There are variations on this theme that avoid the virtual function calls.
You could use boost::function as the arg type, or make ForEachItem a
template member function. Each has their own (dis)advantages.
Either way this allows you to even switch between std::vector and std::map
as the container without modification the clients of GroupOfItems. In the
case of std::map you would redefine:
void GroupOfItems::ForEachItem( const ItemVisitor& aItemVisitor )
{
typedef std::map<...>::iterator tItr;
for_each( tItr lItr = m.begin() ; lItr != m.end(), ++lItr )
{
aItemVisitor( lItr->second );
}
}
Jeff Flinn