I have this Container
class with begin() and end() functions for use with c++11 foreach loops:
class Element
{
//content doesn't matter
};
class Container
{
Element* elements;
int size;
/* constructor, destructor, operators, methods, etc.. */
Element* begin() { return elements; };
Element* end() { return elements + size; };
};
This is now a valid c++11 foreach loop:
Container container;
for (Element& e : container)
{
//do something
}
But now consider this foreach loop:
Container container;
for (Element* e : container)
{
//do something
}
Is it possible to have a foreach loop with Element*
instead of Element&
like this?
This would also have the great advantage of preventing one from typing for (Element e : container)
which would copy the element each time.
In that case begin()
and end()
would have to return Element**
as far as I know.
But sizeof(Element)
is not guaranteed to be sizeof(Element*)
and in most cases they don't match. Incrementing a pointer increments by the base type size which is sizeof(Element)
for incrementing Element*
and sizeof(Element*)
for incrementing Element**
.
So the prefix operator++()
will offset the pointer by a false value and things get crappy. Any ideas how to get this to work?
I agree with LRiO that what you have right now is probably the best solution. It additionally lines up with how the standard containers operate, and taking the path of least surprise for your users is always the best path to take (barring compelling reasons to diverge).
That said, you can certainly get the behavior you want:
class Container
{
// ...
struct iterator {
Element* e;
// this is the important one
Element* operator*() { return e; }
// the rest are just boilerplate
iterator& operator++() { ++e; return *this; }
iterator operator++(int) {
iterator tmp{e};
++*this;
return tmp;
}
bool operator==(iterator rhs) const { return e == rhs.e; }
bool operator!=(iterator rhs) const { return e != rhs.e; }
};
iterator begin() { return {elements}; };
iterator end() { return {elements + size}; };
};
You could consider inheriting from std::iterator
to get the typedefs right, or using boost::iterator_facade
. But this'll at least give you the functionality.
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