I’ll try and keep my sample code very straightforward, but it may have errors as I’m typing it on the spot.
I have a class named Phone.
class Phone
{
public:
Phone(std::string manufacturer, std::string model, std::vector<Feature> features);
private:
std::vector<Features> features;
std::string model;
std::string manufacturer;
};
I have a struct named Feature.
struct Feature
{
Feature(std::string feature, std::string category);
std::string feature;
std::string category;
};
As you can see a phone has a list (vector) of features: ie. bluetooth, GPS, radio, etc, which have a category: networking, navigation, multimedia.
Now information about phones and features are stored in a sqlite3 database.
I have a helper function which will retrieve a particular phone model from the database and return a populated Phone object.
I also have a function which takes in a Phone object and writes the Phone to the database.
The problem is I need to provide the client some way of iterating over the list of Features of a Phone. For starters the database helper needs to know about the features so it can write them to the database. Second the client may need to retrieve a Phone from the database and then display the list of features to the user.
One solution is to add the following functions in class Phone
std::vector<Feature>::iterator begin()
std::vector<Feature>::iterator end()
This is not an ideal solution for me because the client code will not look intuitive – it will appear as if the client is iterating over a Phone, when they are actually iterating over Features.
Another solution is discussed in an article at http://accu.org/index.php/journals/1527 which discusses using a technique named “memberspaces” to expose iterators to client code. It would result in more readable client code, but the implementation is a bit messy in my opinion.
Is there a better solution to the iterator problem, or maybe there is a more suitable design pattern I could be using.
Any feedback would be greatly appreciated.
In your case I would go for better names first:
Examples:
1)
2)
P.S. Given Jonannes’ suggestion and the naming convention used by
boost::rangethe names are nowfeatures_xxx()instead ofxxx_features()(especially since they do make more sense in this context).