I have a class like the one below:
class Foo {
private:
std::map<std::string, Bar*> bars_by_name;
std::map<std::string, Baz*> bazs_by_name;
};
Now I'd like to allow the user to access both collections but hide the implementation detail that I'm storing the objects into std::maps. Instead, I'd like to have member functions that return e.g. const iterators for the collections and possibly even a custom iterator that returns objects from both collections, since Bar and Baz belong to the same class hierarchy. Considering style, what would be the proper way to do this in C++? In Java, I'd probably set the method's return type to Iterable or wrap the collection into an unmodifiableCollection.
You could pass the collection's iterators off as your own.
class Foo {
private:
typedef std::map<std::string, Bar*> BarContainer;
typedef std::map<std::string, Baz*> BazContainer;
public:
typedef BarContainer::const_iterator ConstBarIterator;
ConstBarIterator beginBars() { return bars_by_name.cbegin(); }
ConstBarIterator endBars() { return bars_by_name.cend(); }
typedef BazContainer::const_iterator ConstBazIterator;
ConstBazIterator beginBazs() { return bazs_by_name.cbegin(); }
ConstBazIterator endBazs() { return bazs_by_name.cend(); }
private:
BarContainer bars_by_name;
BazContainer bazs_by_name;
};
This saves you the work of implementing your own iterator, yet leaves you the flexibility of changing your container types later and only requiring callers to recompile.
It doesn't solve the problem of iterating them both together.
Create an interface that hides the details:
class Foo {
public:
void AddBar(std::string name, Bar*);
void RemoveBar(std::string name);
Bar* GetBar(std::string name);
Bar* GetBar(std::string name) const;
void AddBaz(std::string name, Baz*);
void RemoveBaz(std::string name);
Baz* GetBaz(std::string name);
Baz* GetBaz(std::string name) const;
private:
std::map<std::string, Bar*> bars_by_name;
std::map<std::string, Baz*> bazs_by_name;
};
For all the user knows, you could be storing them in a std::pair inside a list, inside a vector, or even using parallel arrays...anything really.
EDIT:
The fact that you are storing it in a map but want the user to iterate over the underlying container smells of a bad/incorrect design. Either only allow them individual access as above or create methods that will do this for them.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With