[Apologies if this question seems opinionated or discussionworthy.]
I have a class which, although not a collection class per se, does contain an arbitrary number of elements which are primarily constructed via an 'append' method:
append(TypeA thingA, TypeB thingB, TypeC thingC);
Significantly, there is not an auxiliary struct or class anywhere tying together a triple of (thingA, thingB, thingC), nor has one been needed so far -- the class works fine as-is.
Today I decided I needed an iterator for this class, that could return all the things I'd added to it, almost as if it were a collection, after all. The question is, what's the best way to return thingA, thingB, and thingC?
I could belatedly define an auxiliary tuple struct, just so that the iterator could return instances of it. But this seemed a little odd.
What I implemented instead was something along the lines of
class FunnyCollectionIter {
FunnyCollection* _ctx;
unsigned int _i;
public:
FunnyCollectionIter();
const TypeA& thingA() const;
const TypeB& thingB() const;
const TypeC& thingC() const;
FunnyCollectionIter& operator=(const FunnyCollectionIter &rhs);
FunnyCollectionIter& operator++();
bool operator==(const FunnyCollectionIter &rhs) const;
// ...
}
};
And I'm using it with code like this:
FunnyCollectionIter it;
for(it = funnycollection.begin(); it != funnycollection.end(); ++it) {
// now do things with it.thingA(), it.thingB(), and it.thingC()
}
But this seems a little odd, too. Normally (in the STL, at least) you access an iterator either using *, or ->first and ->second. But in the scheme I've implemented, there's no *, no ->, no first and second (let alone third?), and the interesting names thingA, thingB, and thingC are methods to invoke, not members to access.
So my question is, is this a poor way to construct an iterator in this situation, and is there a better way?
If it helps, the class is actually a scheduler. The three "things" in question are a duration, a callback, and an optional name. The caller constructs a schedule via one or more calls to append(), and then normally the schedule just runs, but now I have a need for the caller to be able to review the just-constructed schedule. (This is the same class I was referring to in this other question.)
You might split your class to have iterator interface on one side, and specific interface on the other side:
class FunnyWrapper
{
FunnyCollection* _ctx;
unsigned int _i;
public:
const TypeA& thingA() const;
const TypeB& thingB() const;
const TypeC& thingC() const;
// ...
// trick to use operator -> in iterator.
FunnyWrapper* operator ->() { return this; }
};
class FunnyCollectionIter
{
FunnyCollection* _ctx;
unsigned int _i;
public:
FunnyCollectionIter();
FunnyCollectionIter& operator=(const FunnyCollectionIter &rhs);
FunnyCollectionIter& operator++();
bool operator==(const FunnyCollectionIter &rhs) const;
// ...
FunnyWrapper operator->() { return FunnyWrapper{_ctx, _i}; }
FunnyWrapper operator*() { return FunnyWrapper{_ctx, _i}; }
};
Related
I have code like this:
#include <vector>
struct pollfd; // incomplete struct, since i did not included <poll>
struct Status{
// abstract representation of pollfd, epoll_event, kevent
int fd;
int status; // my own status representation
};
class iterator{
public:
hidden_pointer_iterator(const pollfd *pos) : pos(pos){}
bool operator !=(iterator const &other) const{
return ! ( *this == other);
}
bool operator ==(iterator const &other) const;
iterator &operator ++();
Status operator *() const;
private:
const pollfd *pos;
};
class PollSelector{
public:
// ...
iterator begin() const; // pull pointer to fds_.data()
iterator end() const; // pull pointer to fds_.data() + fds_.size()
private:
std::vector<pollfd> fds_;
};
I was able to make it run, by implementing all specific operations in the CPP file.
My question is - is there more "standard" way to do this iterator?
Update
My code compiles and works.
I am qurious if there are something in std that can do all this automatically, without so much coding.
A bit off-topic, IMO, this code abstracts away the wrong thing.
You should rather have multiple implementations of your demultiplexer engine interface, one that uses epoll, another for kevent, etc.. Demultiplexer engine interface is the one that allows you to register callbacks for file descriptor events, timers, signals, cross-thread, etc..
On Linux, there may be little point to using anything else but epoll.
I'm having a custom structure called SortedArrayList<T> which sorts its elements according to a comparator, and I would like to prevent assigning using operator[].
Example:
ArrayList.h
template <typename T> class ArrayList : public List<T> {
virtual T& operator[](const int& index) override; //override List<T>
virtual const T operator[](const int& index) const override; //override List<T>
}
SortedLinkedList.h with following operators
template <typename T> class SortedArrayList : public ArrayList<T> {
public:
SortedArrayList<T>(const std::function<bool(const T&, const T&)>& comparator);
T& operator[](const int& index) override; //get reference (LHS)
const T operator[](const int& index) const override; //get copy (RHS)
}
Test.h
ArrayList<int>* regular = new ArrayList<int>();
ArrayList<int>* sorted = new SortedArrayList<int>(cmpfn);
(*regular)[0] == 5; //allow
(*regular)[0] = 5; //allow
(*sorted)[0] == 7; //allow
(*sorted)[0] = 7; //except
Is this operation possible?
By prevent I mean throwing an exception or something what will warn user to not do it.
Prefer aggregation over inheritance:
template <typename T> class SortedArrayList {
ArrayList<T> m_the_list;
public:
SortedArrayList<T>(const std::function<bool(const T&, const T&)>& comparator);
const T& operator[](const int& index) const {return m_the_list[index];}; // always get const reference
// Can act as a *const* ArrayList<T>, but not as a mutable ArrayList<T>, as that would violate Liskov's substitution principle.
operator const ArrayList<T>&() const {return m_the_list;}
}
As Stephen Newell correctly points out, when you're using inheritance, you're guaranteeing your class SortedArrayList can act as an ArrayList in every possible scenario. This is clearly not the case in your example.
You can read more here about how violating Liskov's Substitution Principle is a bad idea.
You should not do this. It indicates an improper design See the C++ FAQ on Inheritance. Your subclass doesn't fulfill the "is-a" requirement for public inheritance if it can't be used in all ways as the base class (LSP).
If you want to have one type of container that allows member replacement and another that doesn't, then the define the base class that just allows const member access (no need to make it virtual). Then branch from there to MutableList and ImmutableList, and let SortedArrayList derive from Immutable list.
Seems to me like the best practice here would be to implement an at(const int& index) method instead of overloading []. That would be more clear to the user of the interface anyway.
There is a similar function in std::map and other std data structures. For example: http://www.cplusplus.com/reference/map/map/at/
Why do you pass the index as reference at all? Absolutely no need for...
I personally recommend to use unsigned integer types for array indices (what would be the meaning of a negative index anyway???).
const for a type returned by value is (nearly) meaningless - it will be copied to another variable anyway (which then will be modifiable), but you prevent move semantics...
So:
T& operator[](unsigned int index); //get reference (LHS)
T operator[](unsigned int index) const; //get copy (RHS)
(Just some improvement suggestions...)
Now to the actual question: Disallowing modification is quite easy:
//T& operator[](unsigned int index); //get reference (LHS)
T const& operator[](unsigned int index) const; //get copy (RHS)
Just one single index operator, always returning const reference... If user can live with reference, fine, otherwise he/she will copy the value anyway...
Edit in adaption to modified question:
As now inheritance is involved, the stuff gets more complicated. You cannot just get rid of some inherited function, and the inherited one will allow element modification.
In the given situation, I'd consider a redesign (if possible):
class ArrayListBase
{
public:
T const& operator[](unsigned int index) const;
// either copy or const reference, whichever appears more appropriate to you...
};
class ArrayList : public ArrayListBase
{
public:
using ArrayListBase::operator[];
T& operator[](unsigned int index);
}
class SortedArrayList : public ArrayListBase
{
public:
// well, simply does not add an overload...
}
The insertion function(s) might be pure virtual in the base class (where a a common interface appears suitable) or only available in the derived classes. Decide you...
A set of APIs that I commonly use follow a linked-list pattern:
struct SomeObject
{
const char* some_value;
const char* some_other_value;
SomeObject* next;
}
LONG GetObjectList( SomeObject** list );
void FreeObjectList( SomeObject* list );
This API is not mine and I cannot change it.
So, I'd like to encapsulate their construction/destruction, access, and add iterator support. My plan is to do something like this:
/// encapsulate access to the SomeObject* type
class MyObject
{
public:
MyObject() : object_( NULL ) { };
MyObject( const SomeObject* object ) : object_( object ) { };
const char* SomeValue() const
{
return NULL != object_ ? object_->some_value : NULL;
};
const char* SomeValue() const
{
return NULL != object_ ? object_->some_other_value : NULL;
};
private:
SomeObject* object_;
}; // class MyObject
bool operator==( const MyObject& i, const MyObject& j )
{
return // some comparison algorithm.
};
/// provide iterator support to SomeObject*
class MyObjectIterator
: public boost::iterator_adaptor< MyObjectIterator,
MyObject*,
boost::use_default,
boost::forward_traversal_tag >
{
public:
// MyObjectIterator() constructors
private:
friend class boost::iterator_core_access;
// How do I cleanly give the iterator access to the underlying SomeObject*
// to access the `next` pointer without exposing that implementation detail
// in `MyObject`?
void increment() { ??? };
};
/// encapsulate the SomeObject* creation/destruction
class MyObjectList
{
public:
typedef MyObjectIterator const_iterator;
MyObjectList() : my_list_( MyObjectList::Create(), &::FreeObjectList )
{
};
const_iterator begin() const
{
// How do I convert a `SomeObject` pointer to a `MyObject` reference?
return MyObjectIterator( ??? );
};
const_iterator end() const
{
return MyObjectIterator();
};
private:
static SomeObject* Create()
{
SomeObject* list = NULL;
GetObjectList( &list );
return list;
};
boost::shared_ptr< void > my_list_;
}; // class MyObjectList
My two questions are:
How do I cleanly give MyObjectIterator access to the underlying SomeObject to access the next pointer in the linked list without exposing that implementation detail in MyObject?
In MyObjectList::begin(), how do I convert a SomeObject pointer to a MyObject reference?
Thanks,
PaulH
Edit: The linked-list APIs I'm wrapping are not mine. I cannot change them.
First, of course, for real use, you almost certainly shouldn't be writing your own linked list or iterator at all. Second, good uses for linked lists (even one that's already written, debugged, etc.) are also pretty rare -- except in a few rather unusual circumstances, you should probably use something else (most often vector).
That said, an iterator is typically a friend (or nested class) of the class to which it provides access. It provides the rest of the world with an abstract interface, but the iterator itself has direct knowledge of (and access to) the internals of the linked list (or whatever container) to which it provides access). Here's a general notion:
// warning: This is really pseudo code -- it hasn't been tested, and would
// undoubtedly require a complete rewrite to even compile, not to mention work.
template <class T>
class linked_list {
public:
class iterator;
private:
// A linked list is composed of nodes.
// Each node has a value and a pointer to the next node:
class node {
T value;
node *next;
friend class iterator;
friend class linked_list;
public:
node(T v, node *n=NULL) : value(v), next(n) {}
};
public:
// An iterator gives access to the linked list.
// Operations:
// increment: advance to next item in list
// dereference: access value at current position in list
// compare: see if one iterator equals another
class iterator {
node *pos;
public:
iterator(node *p=NULL) : pos(p) {}
iterator operator++() {
assert(pos);
pos = pos->next;
return *this;
}
T operator*() { return pos->value; }
bool operator!=(iterator other) { return pos != other.pos; }
};
iterator begin() { return iterator(head); }
iterator end() { return iterator(); }
void push_front(T value) {
node *temp = new node(value, head);
head = temp;
}
linked_list() : head(NULL) {}
private:
node *head;
};
To work along with the algorithms in the standard library, you have to define quite a bit more than this tried to (e.g., typedefs like value_type and reference_type). This is only intended to show the general structure.
My advice: Trash this and use an existing slist<> implementation. IIRC, it will be in C++1x, so your compiler(s) might already support it. Or it might be in boost. Or take it from someplace else.
Wherever you get it from, what you get has all these problems already solved, is likely very well tested, therefore bug-free and fast, and the code using it is easily recognizable (looking at it many of us would immediately see what it does, because it's been around for a while and it's going to to be part of the next standard).
The last time I wrote my own list class was before the STL became part of the C++ standard library.
Ok, since you're stuck with the API you have, here's something that might get you started:
class MyObjectList
{
public:
typedef SomeObject value_type;
// more typedefs
class iterator {
public:
typedef SomeObject value_type;
// more typedefs
iterator(SomeObject* pObj = NULL)
: pObj_(pObj) {}
iterator& operator++() {if(pObj_)pObj_ = pObj_->next;}
iterator operator++(int) {iterator tmp(*this);
operator++();
return tmp;}
bool operator==(const iterator& rhs) const
{return pObj_ == rhs.pObj_;}
bool operator!=(const iterator& rhs) const
{return !operator==(rhs);}
value_type& operator*() {return pObj_;}
private:
SomeObject* pObj_;
};
class const_iterator {
public:
typedef SomeObject value_type;
// more typedefs
const_iterator(const SomeObject* pObj = NULL)
: pObj_(pObj) {}
iterator& operator++() {if(pObj_)pObj_ = pObj_->next;}
iterator operator++(int) {iterator tmp(*this);
operator++();
return tmp;}
bool operator==(const iterator& rhs) const
{return pObj_ == rhs.pObj_;}
bool operator!=(const iterator& rhs) const
{return !operator==(rhs);}
const value_type& operator*() {return pObj_;}
private:
const SomeObject* pObj_;
};
MyObjectList() : list_() {GetObjectList(&list_;);}
~MyObjectList() {FreeObjectList(list_);}
iterator begin() {return list_ ? iterator(list_)
: iterator();}
const_iterator begin() const {return list_ ? const_iterator(list_)
: const_iterator();}
iterator end () {return iterator(getEnd_());}
const_iterator end () const {return const_iterator(getEnd_());}
private:
SomeObject* list_;
SomeObject* getEnd_()
{
SomeObject* end = list_;
if(list_)
while(end->next)
end = end->next;
return end;
}
};
Obviously, there's more to this (for example, I believe const and non-const iterators should be comparable, too), but that shouldn't be hard to add to this.
From what you said, you probably have a BIG legacy code using your struct SomeObject types but you want to play nicely with new code and use iterators/stl containers.
If that's the case, you will not be able to (in an easy way) use your new created iterator in all the legacy code base, since that will be changing a lot of code, but, you can write a templated iterator that, if your structs follow the same pattern, having a next field, will work.
Something like this (I haven't tested nor compiled it, it's just an idea):
Suppose you have your struct:
struct SomeObject
{
SomeObject* next;
}
You will be able to create something like this:
template <class T>
class MyIterator {
public:
//implement the iterator abusing the fact that T will have a `next` field, and it is accessible, since it's a struct
};
template <class T>
MyIterator<T> createIterator(T* object) {
MyIterator<T> it(object);
return it;
}
If you implement your iterator correctly, you will be able to use all the STL algorithms with your old structs.
PS.: If you're in a scenario of some legacy code with this kind of structs, I do too, and I implemented this workaround. It works great.
You would make MyObjectIterator a friend of MyObject. I don't see any better way. And really I think it's reasonable that iterators get whatever special friend access is necessary for them to perform their duties.
You don't seem to have considered how and where your MyObject instance are going to be stored. Or perhaps that's what this question is coming out of. It seems like you would have to have a separate linked list of MyObjects in your MyObjectList. Then at least MyObjectList::begin() can just grab the first MyObject of your internal linked list of them. And if the only operations that may modify or rearrange this list only ever happen through the iterators you provide, then you can problem keep these lists in synch without too much trouble. Otherwise, if there are functions in the API you're using that take the raw SomeObject linked list and manipulate it, then you may have trouble.
I can see why you've tried to design this scheme, but having separate MyObjects that point to SomeObjects even through SomeObjects themselves make up the real list structure.... That is not an easy way to wrap a list.
The simplest alternative is just to do away with MyObject completely. Let your iterators work against SomeObject instances directly and return those when dereferenced. Sure that does expose SomeObject to the outside, particularly its next member. But is that really a big enough problem to justify a more complex scheme to wrap it all up?
Another way to deal with might be to have MyObject privately inherit from SomeObject. Then each SomeObject instance can be downcast as a reference to a MyObject instance and given to the outside world that way, thus hiding the implemtation details of SomeObject and only exposing the desired public member functions. The standard probably doesn't guarantee this will work, but in practice since they'll likely have the exact same memory layouts you may be able to get away with it. However, I'm not sure that I would actually ever try such a thing in a real program unless absolutely necessary.
The last alternative I can think of is just to transfer the data into a list of more convenient data structures after being given to you by this API. And then of course transfer it back into a raw SomeObject list only if necessary to pass it back to the API. Just make your own SomeObjectData or whatever to store the strings and put them in a std::list. Whether or not this is actually feasible for you really depends on how this data is used in the context of the API you've mentioned. If there are other API functions that modify SomeObject lists and you need to use them frequently, then constantly converting SomeObject lists to and from std::list<SomeObjectData> could be annoying.
I've seen some very good answers so far but I fear they might be "bare".
Before blindingly charge in let's examine the requirements.
As you noticed the structure is similar to a singly linked list, the C++0x standard defines such a structure, called forward_list. Read up its interface, yours should come close.
The iterator type will be ForwardIterator.
I would like to expose one very annoying fact though: who's responsible for the memory ?
I am worried because there's no copy facility in the interface you've provided, so should we disable the copy constructor and assignment operator of our new list class ?
Implementation is easy, there's enough on this page even though the iterator don't properly implement the iterator traits in general, but I would consider ditching this idea completely and move on to a better scheme:
class MyObject { public: ... private: SomeObject mData; };
Wrapping up GetObjectList and returning a deque<MyObject>, I guess the LONG returns the number of items ?
I have to work with an application in C++ similar to a phone book: the class Agenda with an STL list of Contacts.Regarding the contacts hierarchy,there is a base-class named Contact(an abstract one),and the derived classes Friend and Acquaintance(the types of contact).
These classes have,for instance, a virtual method called getName,which returns the name of the contact.
Now I must implement the Composite pattern by adding another type of contact,Company(being derived from Contact),which also contains a collection of Contacts(an STL list as well),that can be either of the "leaf" type(Friends or Acquaintances),or they can be Companies as well.
Therefore,Company is the Compound type.
The question is: how and where can I implement an STL find_if to search the contact with a given name(via getName function or suggest me smth else) both among the "leaf"-type Contact and inside the Company collection?
In other words,how do I traverse the tree in order to find possible matches there too,using an uniform function definition?
I hope I was pretty clear...
Well, one way to do it:
virtual contact* contact::findContact(std::string name)
{
if(m_name == name) {return this;}
return NULL;
}
Then:
contact * Company::findContact(std::string name)
{
if(!contact::findContact(name) )
{
//For each contact in the contact list, findContact(name)
//If we find something, return that.
//Otherwise return null.
}
return this;
}
What you're doing is asking each node to find the one you're looking for, without caring what type of node (leaf or otherwise) it is. Each node then checks itself, and, for those with child nodes, their children.
List is the wrong type for a large type of contacts since you might have a O(N) to find the last contact or even to find no contact.
I suggest you to use a hash map (unordered_map from boost/tr1) or a regular map so you will be able to find them by ID or their name using a key.
Also sounds like a company should just be a tree of contacts.
You can find tree implementations here.
You transvase through the tree to find the node you need.
"Now I must implement the Composite pattern by adding another type of contact,Company(being derived from Contact),which also contains a collection of Contacts(an STL list as well),that can be either of the "leaf" type(Friends or Acquaintances),or they can be Companies as well"
You could create a stl-compatible composite iterator for Company.
class Company : public Contact {
std::list<Contact *> contactList;
//snip...other private members
friend class CompanyIterator;
friend class ConstCompanyIterator;
public:
// nested iterator classes
class CompanyIterator : public std::iterator<std::forward_iterator_tag, Contact *> {
friend class Company;
// pair<>.first is the iterator obtain by calling begin()
// pair<>.second is the end iterator
std::stack< std::pair< std::list<Contact *>::iterator,
std::list<Contact *>::iterator> > iters_stack;
Contact *pCurrentContact;
Company *pCompany; // This is the top level company which will be iterated.
public:
explicit CompanyIterator(Company &c);
// Required forward iterator methods follow
CompanyIterator();
CompanyIterator(const CompanyIterator&);
CompanyIterator& operator=(const CompanyIterator& other);
Contact &operator*() const;
Contact *operator->() const;
CompanyIterator& operator++();
CompanyIterator operator++(int);
bool operator==(const CompanyIterator& x) const;
bool operator!=(const CompanyIterator& x) const;
};
// nested iterator class
class ConstCompanyIterator : public std::iterator<std::forward_iterator_tag,
const Contact *> {
friend class Company;
// We use CompanyIterator to implement ConstCompanyIteraor
CompanyIterator inner_iter; // fwd operations here,
// using "const_cast<Company *>(this)->method()"
public:
explicit ConstCompanyIterator(const Company & dir);
// This ctor will function as a cast operator, to convert a CompanyIterator
// into a ConstCompanyIterator
ConstCompanyIterator(const CompanyIterator &iter);
// Required forward iterator methods follow
ConstCompanyIterator();
ConstCompanyIterator(const ConstCompanyIterator&);
ConstCompanyIterator& operator=(const ConstCompanyIterator& other);
const Contact &operator*() const;
const Contact *operator->() const;
ConstCompanyIterator& operator++();
ConstCompanyIterator operator++(int);
bool operator==(const ConstCompanyIterator& x) const;
bool operator!=(const ConstCompanyIterator& x) const;
};
typedef CompanyIterator iterator;
typedef ConstCompanyIterator const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
// snip... other Company public methods
};
For the implementation of the forward iterator methods given above, see the Composite Iterator code on Github. Most of the implementation is in Directory.cpp. The github code is for composite pattern that models a file system. Class Directory is the composite. Class File is the leaf class. Class Node is the base component class.
The functor for find_if would look like
FindIfFunctor {
std::string name;
public:
FindIfFunctor(const std::string& n) : name(n) {}
bool operator()(const Contact& c) { return c.getName().compare(name); }
};
Finally, the find_if code
Company c;
// snip... stuff gets added to company
string someName("IBM");
find_if(c.begin(), c.end(), FindIfFunctor(someName));
I'd like to design a class Foo that stores various data of different types and returns iterators over them. It's supposed to be generic, so the user of Foo does not know how the data is stored (Foo could be using std::set or std::vector or whatever).
I'm tempted to write an interface like this:
class Foo {
class FooImpl;
FooImpl* impl_;
public:
const Iterator<std::string>& GetStrings() const;
const Iterator<int>& GetInts() const;
};
where Iterator is something like this (like iterators in .NET):
template<class T>
class Iterator {
public:
const T& Value() const = 0;
bool Done() const = 0;
void Next() = 0;
};
But I know that kind of iterator is not standard in C++, and it's better to use iterators the way the STL does, so you can use the STL algorithms on them.
How can I do that? (Do I need iterator_traits by any chance?)
Do you understand why the STL chose to put iterator implementation details in the header file? JIT frameworks are able to inline across compilation units, but C++ can only inline within a compilation unit. Advancing through a sequence is much faster when inlined, the cost of a function call dominates actually traversing the data structure.
If you really want to hide the implementation details, go ahead. You could make an STL-compatible iterator that implements operator++ and operator!= and operator-> in terms of protected virtual functions, the Next, Done, and Value you've mentioned would be decent names. Just expect to pay for the encapsulation with lower performance.
A c++ class with iterators has to provide at least two functions if they have to work with the std library
iterator begin() //returns an iterator at starting pos
iterator end() //returns an iterator one past end or just invald
The iterator has to overload the increment operators, equals and *
iterator operator++()
iterator operator==()//make sure that an invalid iterator equals end()
T& operator*()
You can use the iterator class to wrap around the iterator of the internal storage to ensure that the user is limited to these methods.
template <typename T> iter
{
iter(T::iterator& intern)
T::value_type& operator*(){return *intern}
iter operator++(){return iter(++intern);}
bool operator==(iter const& other)const{return intern == other.intern;}
}
Where T is the type of your container.(The class is incomplete and I may have mixed something up)
It almost looks like you're trying to create container-independent code, which is not (in general) a good idea, unless you are writing an algorithm which can operate solely with iterators. (See Scott Myers Effective STL Item 2: Beware the illusion of container-independent code)
The problem is that most of the standard containers do not provide overlapping functionality. If you're writing code for a particular container, assume you're writing code for that container. Don't bother trying to make it container-independent.
Use a typedef to return an boost::iterator_range. For example (never mind the names),
class Container
{
typedef std::vector<int> Collection;
public:
typedef boost::iterator_range<Collection::iterator> CollectionRange;
typedef Collection::iterator CollectionIterator;
Range range() const {
return make_iterator_range(collection_.begin(), collection_.end());
}
private:
Collection collection_;
};
The user code will be
Container c;
// ...
FOREACH(int i, c.range()) { //... }
Container::Range r = c.range();
for(Container::iterator j = r.begin(); j!= r.end(); j++) { // ... }
This is not generic, but the same idea can be used with templates.
To fulfill the requirement that the particular container (vector, set, ...) is not mentioned in the header file, and the user will be able to iterate over all strings, is to use the visitor pattern. The downside, of course, is that the user won't be able to use the STL algorithms on the strings.
// foo.h
class StringVisitor {
public:
void accept(const std::string& str) {
std::cout << str << std::endl;
}
};
class Foo {
class Impl;
Impl* impl_;
public:
Foo();
~Foo();
void VisitStrings(StringVisitor v) const;
};
// foo.cc
class Foo::Impl {
typedef std::vector<std::string> StringContainer;
StringContainer str_;
public:
Impl() {
str_.push_back("a");
str_.push_back("b");
}
void VisitStrings(StringVisitor v) const {
for(StringContainer::const_iterator it = str_.begin();
it != str_.end(); ++it){
v.accept(*it);
}
}
};
Foo::Foo() : impl_(new Impl()) {}
Foo::~Foo() {delete impl_;}
void Foo::VisitStrings(StringVisitor v) const {
impl_->VisitStrings(v);
}
// main.cc
int main() {
Foo foo;
foo.VisitStrings(StringVisitor());
return 0;
}