I have a container which is responsible for managing a set of attributes. The class partially looks something like this:
class AttributeSet
{
public:
// ... interface is irrelevant for my question.
private:
std::vector<boost::shared_ptr<Attribute> > m_attributes;
};
Attribute is polymorphic so the attributes have to be stored as pointers however they can never be NULL.
I want to use this class with BOOST_FOREACH, like this:
BOOST_FOREACH(const Attribute &attribute, attributeSet)
{
...
}
According to BOOST_FOREACH documentation,
The support for STL containers is very general; anything that looks like an STL container counts. If it has nested iterator and const_iterator types and begin() and end() member functions, BOOST_FOREACH will automatically know how to iterate over it.
So I updated my class to look something like this:
class AttributeSet
{
public:
typedef std::vector<boost::shared_ptr<Attribute> > container;
typedef container::iterator iterator;
typedef container::const_iterator const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
private:
container m_attributes;
};
So now I can do this:
BOOST_FOREACH(const boost::shared_ptr<Attribute> &attribute, attributeSet)
{
...
}
This is nice however I don't like that it exposes the attributes as pointers. From the caller side, this is noise and would generate pointless NULL checks.
I have a few ideas on how to correct the problem. For example, something like this would be nice:
class AttributeSet
{
public:
typedef std::vector<boost::shared_ptr<Attribute> > container;
typedef iterator_dereference_adapter< container::iterator > iterator;
typedef iterator_dereference_adapter< container::const_iterator > const_iterator;
iterator begin() { return iterator(m_attributes.begin()); }
iterator end() { return iterator(m_attributes.end()); }
const_iterator begin() const { return const_iterator(m_attributes.begin()); }
const_iterator end() const { return const_iterator(m_attributes.end()); }
private:
container m_attributes;
};
The 'iterator_dereference_adapter' class is somewhat self-explanatory. It would wrap an existing iterator of pointers and dereference the pointer values.
So finally, my question...
Before I go off and try to write this adapter, is there something in STL or Boost like this class?
I'm open to other ideas.
Boost has indirect_iterator which is exactly inteded for wrapping an iterator to pointer type and automatically dereferencing.
Here's a fairly normal encapsulation of an STL container which allows the user of Cfoo to iterate the container without allowing changes to the innards.
#include <vector>
class Cfoo
{
public:
class Cbar
{
/* contents of Cbar */
};
typedef std::vector<Cbar> TbarVector;
typedef TbarVector::const_iterator const_iterator;
public:
const_iterator begin() const { return( barVector_.begin() ); }
const_iterator end() const { return( barVector_.end() ); }
private:
TbarVector barVector_;
};
So far, so good. We can iterate the container like this:
Cfoo myFoo;
for (Cfoo::const_iterator it = myFoo.begin(); it != myFoo.end(); ++it)
{
it->DoSomething();
}
Now I want to replace the std::vector with say a nested std::vector:
public:
typedef std::vector<Cbar> TbarVectorInner;
typedef std::vector<TbarVectorInner> TbarVectorOuter;
private:
TbarVectorOuter barContainer_;
But I want to be able to iterate over all the instances of Cbar in the same way as before, exposing a const_iterator, and a begin()const and an end()const method.
I'm not clear how to do that, though I suspect it involves writing a custom iterator. Any thoughts?
None of the standard iterators are able to iterate over more than a single container, so your assumption is correct - you'll have to write a custom iterator.
It is possible to do this in a generic fashion, if you have an intermediate iterator that returns pairs of (begin,end) iterators to the inner containers.
Some untested code to get started:
template<typename T, typename OuterIterator, typename InnerIterator>
class Iterator2d : std::Iterator
{
public:
Iterator2d(OuterIterator begin, OuterIterator end) : m_begin(begin), m_end(end), m_currentOuter(begin) {
if (m_currentOuter != m_end)
m_currentInner = m_begin->first;
Normalize();
}
Iterator2d & operator++()
{
if (m_currentOuter != m_end)
{
++m_currentInner;
Normalize();
}
return *this;
}
T & operator*()
{
return *m_currentInner;
}
private:
void Normalize()
{
while (m_currentOuter != m_end && m_currentInner == m_currentOuter->second)
{
++m_currentOuter;
if (m_currentOuter != m_end)
m_currentInner = m_currentOuter->first;
}
}
OuterIterator m_begin;
OuterIterator m_end;
OuterIterator m_currentOuter;
InnerIterator m_currentInner;
};
This is just a start, I may come back to finish it - or not, depending on this implementation already covers the same ground.
As far as I can tell in c++ there is no common base class that covers both iterator and reverse_iterator.
The only suggestion I have seen so far is to get around this using templates (
How to write a function that takes an iterator or collection in a generic way? )
However this solution doesn't seem to work for me.
class MyClass
{
template<typename Iter> Iter* generate_iterator(...params...)
{
//returns either a vector::iterator or vector::reverse_iterator
}
template<typename Iter> void do_stuff(Iter *begin, Iter *end)
{
//does stuff between elements specified by begin and end
//I would like this function to remain agnostic of which direction it is working in!
}
void caller()
{
//I would like this function to remain agnostic of which direction it is working in too...
do_stuff(generate_iterator(blah),generate_iterator(foo));
}
};
In this case, generate_iterator() cannot be used as desired because the compiler complains "generate_iterator is not a member of class MyClass" presumably because I haven't specified it (which I can't in practice as caller should be agnostic of the iterator type).
Can anyone help? Thanks in advance!
edit: as Mark B pointed out generate_iterator must return a pointer - now corrected
update: just started using this http://thbecker.net/free_software_utilities/type_erasure_for_cpp_iterators/start_page.html and it seems to work...
You can create your own iterator class that knows how to go both directions. Encapsulate both types of iterator and internally select whichever one you were initialized with.
Here's a start:
template<typename Container>
class BiIterator
{
public:
BiIterator(Container::iterator i) : m_fwd(i), m_isforward(true) {}
BiIterator(Container::reverse_iterator i) : m_rev(i), m_isforward(false) {}
bool operator==(const BiIterator & left, const BiIterator & right);
Container::value_type & operator*()
{
if (m_isforward)
return *m_fwd;
return *m_rev;
}
const Container::value_type & operator*() const;
BiIterator & operator++()
{
if (m_isforward)
++m_fwd;
else
++m_rev;
return *this;
}
private:
Container::iterator m_fwd;
Container::reverse_iterator m_rev;
bool m_isforward;
};
In C++ you can't write a function that returns two different types. In your template case it will return one or the other depending on the instantiation. You could possibly return a base pointer to a polymorphic iterator but that would cause me to ask what you're really trying to do here. Even the standard containers don't try to do that: They have begin and rbegin to distinguish properly. I would suggest having two separate functions that each do the right thing and return one type of iterator or the other as context dictates.
As a side, note that you can't implicitly determine a template instantiation of a type that's only used for the return type of a function.
By using boost tuple and boost any , your problem can be easily solved. I wrote a example by using boost::any , see below:
#include <boost/any.hpp>
using boost::any_cast;
#define MSG(msg) cout << msg << endl;
boost::any getIterator(std::vector<int>& vec, bool bReverse)
{
if(!bReverse)
return boost::any(vec.begin());
else
return boost::any(vec.rbegin());
}
int main()
{
std::vector<int> myvec;
myvec.push_back(1);
myvec.push_back(2);
myvec.push_back(3);
typedef std::vector<int>::iterator vecIter;
typedef std::vector<int>::reverse_iterator vecRIter;
try
{
boost::any iter = getIterator(myvec, false);
boost::any iter2 = getIterator(myvec, true);
vecIter it1 = any_cast<vecIter>(iter);
vecRIter it2 = any_cast<vecRIter>(iter2);
MSG(*it1);//output 1
MSG(*it2);//output 3
return true;
}
catch(const boost::bad_any_cast &)
{
return false;
}
}
Use boost::variant or boost::any.
boost::variant< reverse_iterator, iterator >
generate_iterator(...) {
if(...) return iterator();
else return reverse_iterator();
}
// user code
boost::variant< reverse_iterator, iterator > v = generate_iterator();
if(reverse_iterator* it = boost::get<reverse_iterator>(v))
...;
else if(...)
...;
Although the variant is better accessed through a visitor.
The downside is that you need some boiler plate to extract the proper type and is exactly the reason why something like any_iterator might be a more sensible choice.
I'm writing an own container class and have run into a problem I can't get my head around. Here's the bare-bone sample that shows the problem.
It consists of a container class and two test classes: one test class using a std:vector which compiles nicely and the second test class which tries to use my own container class in exact the same way but fails miserably to compile.
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
template <typename T>
class MyContainer
{
public:
class iterator
{
public:
typedef iterator self_type;
inline iterator() { }
};
class const_iterator
{
public:
typedef const_iterator self_type;
inline const_iterator() { }
};
iterator begin() {
return iterator();
}
const_iterator begin() const {
return const_iterator();
}
};
// This one compiles ok, using std::vector
class TestClassVector
{
public:
void test() {
vector<int>::const_iterator I=myc.begin();
}
private:
vector<int> myc;
};
// this one fails to compile. Why?
class TestClassMyContainer
{
public:
void test(){
MyContainer<int>::const_iterator I=myc.begin();
}
private:
MyContainer<int> myc;
};
int main(int argc, char ** argv)
{
return 0;
}
gcc tells me:
test2.C: In member function ‘void TestClassMyContainer::test()’:
test2.C:51: error: conversion from ‘MyContainer::iterator’ to non-scalar type ‘MyContainer::const_iterator’ requested
I'm not sure where and why the compiler wants to convert an iterator to a const_iterator for my own class but not for the STL vector class. What am I doing wrong?
When you call begin() the compiler by default creates a call to the non-const begin(). Since myc isn't const, it has no way of knowing you mean to use the const begin() rather than the non-const begin().
The STL iterator contains a cast operator which allows an iterator to be silently converted to a const_iterator. If you want this to work you need to add one as well like so:
class iterator
{
public:
typedef iterator self_type;
inline iterator() { }
operator const_iterator() { return const_iterator(); }
};
or allow const_iterator to be constructed from an iterator like so:
class const_iterator
{
public:
typedef const_iterator self_type;
const_iterator(iterator& ) {}
inline const_iterator() { }
};
You should have a look to the Boost.Iterators library, especially the iterator_facade and iterator_adaptor sections. They contain a build-up of an iterator "from scratch".
It will show you how to write iterators without too much duplication, because most of the times the code the const and non-const versions is about the same, apart from the const qualification itself. Using templates it's possible to write it once, then declare two different types, and that's what the library documentation illustrates.
In containers iterator type must be convertible to const_iterator. It is needed for the cases where you iterate through a mutable container using a non-mutable (const) iterator as this makes perfect sense. In your case myc is mutable (non-const), but you create a const iterator on that.
Having toyed with this I suspect it isn't remotely possible, but I thought I'd ask the experts. I have the following C++ code:
class IInterface
{
virtual void SomeMethod() = 0;
};
class Object
{
IInterface* GetInterface() { ... }
};
class Container
{
private:
struct Item
{
Object* pObject;
[... other members ...]
};
std::list<Item> m_items;
};
I want to add these methods to Container:
MagicIterator<IInterface*> Begin();
MagicIterator<IInterface*> End();
In order that callers can write:
Container c = [...]
for (MagicIterator<IInterface*> i = c.Begin(); i != c.End(); i++)
{
IInterface* pItf = *i;
[...]
}
So essentially I want to provide a class which appears to be iterating over some collection (which the caller of Begin() and End() is not allowed to see) of IInterface pointers, but which is actually iterating over a collection of pointers to other objects (private to the Container class) which can be converted into IInterface pointers.
A few key points:
MagicIterator is to be defined outside Container.
Container::Item must remain private.
MagicIterator has to iterate over IInterface pointers, despite the fact that Container holds a std::list<Container::Item>. Container::Item contains an Object*, and Object can be used to fetch IInterface*.
MagicIterator has to be reusable with several classes which resemble Container, but might internally have different list implementations holding different objects (std::vector<SomeOtherItem>, mylist<YetAnotherItem>) and with IInterface* obtained in a different manner each time.
MagicIterator should not contain container-specific code, though it may delegate to classes which do, provided such delegation is not hard coded to to particular containers inside MagicIterator (so is somehow resolved automatically by the compiler, for example).
The solution must compile under Visual C++ without use of other libraries (such as boost) which would require a license agreement from their authors.
Also, iteration may not allocate any heap memory (so no new() or malloc() at any stage), and no memcpy().
Thanks for your time, even if you're just reading; this one's really been bugging me!
Update: Whilst I've had some very interesting answers, none have met all the above requirements yet. Notably the tricky areas are i) decoupling MagicIterator from Container somehow (default template arguments don't cut it), and ii) avoiding heap allocation; but I'm really after a solution which covers all of the above bullets.
I think you have two separate issues here:
First, create an iterator that will return the IInterface* from your list<Container::Item>. This is easily done with boost::iterator_adaptor:
class cont_iter
: public boost::iterator_adaptor<
cont_iter // Derived
, std::list<Container::Item>::iterator // Base
, IInterface* // Value
, boost::forward_traversal_tag // CategoryOrTraversal
, IInterface* // Reference :)
>
{
public:
cont_iter()
: cont_iter::iterator_adaptor_() {}
explicit cont_iter(const cont_iter::iterator_adaptor_::base_type& p)
: cont_iter::iterator_adaptor_(p) {}
private:
friend class boost::iterator_core_access;
IInterface* dereference() { return this->base()->pObject->GetInterface(); }
};
You would create this type as inner in Container and return in from its begin() and end() methods.
Second, you want the runtime-polymorphic MagicIterator. This is exactly what any_iterator does. the MagicIterator<IInterface*> is just any_iterator<IInterface*, boost::forward_traversal_tag, IInterface*>, and cont_iter can be just assigned to it.
Create an abstract IteratorImplementation class:
template<typename T>
class IteratorImplementation
{
public:
virtual ~IteratorImplementation() = 0;
virtual T &operator*() = 0;
virtual const T &operator*() const = 0;
virtual Iterator<T> &operator++() = 0;
virtual Iterator<T> &operator--() = 0;
};
And an Iterator class to wrap around it:
template<typename T>
class Iterator
{
public:
Iterator(IteratorImplementation<T> * = 0);
~Iterator();
T &operator*();
const T &operator*() const;
Iterator<T> &operator++();
Iterator<T> &operator--();
private:
IteratorImplementation<T> *i;
}
Iterator::Iterator(IteratorImplementation<T> *impl) :
i(impl)
{
}
Iterator::~Iterator()
{
delete i;
}
T &Iterator::operator*()
{
if(!impl)
{
// Throw exception if you please.
return;
}
return (*impl)();
}
// etc.
(You can make IteratorImplementation a class "inside" of Iterator to keep things tidy.)
In your Container class, return an instance of Iterator with a custom subclass of IteratorImplementation in the ctor:
class ObjectContainer
{
public:
void insert(Object *o);
// ...
Iterator<Object *> begin();
Iterator<Object *> end();
private:
class CustomIteratorImplementation :
public IteratorImplementation<Object *>
{
public:
// Re-implement stuff here.
}
};
Iterator<Object *> ObjectContainer::begin()
{
CustomIteratorImplementation *impl = new CustomIteratorImplementation(); // Wish we had C++0x's "var" here. ;P
return Iterator<Object *>(impl);
}
Doesn't sound too complicated. You can define the iterator outside. You can also use typedefs. Something like this would fit i think. Note that it would be way cleaner if that MagicIterator would be not a free template, but a member of Item, typedefed in Container maybe. As it's now, there is a cyclic reference in it, which make it necassary to write some ugly workaround code.
namespace detail {
template<typename T, typename U>
struct constify;
template<typename T, typename U>
struct constify<T*, U*> {
typedef T * type;
};
template<typename T, typename U>
struct constify<T*, U const*> {
typedef T const * type;
};
}
template<typename DstType,
typename Container,
typename InputIterator>
struct MagicIterator;
class Container
{
private:
struct Item
{
Object* pObject;
};
std::list<Item> m_items;
public:
// required by every Container for the iterator
typedef std::list<Item> iterator;
typedef std::list<Item> const_iterator;
// convenience declarations
typedef MagicIterator< IInterface*, Container, iterator >
item_iterator;
typedef MagicIterator< IInterface*, Container, const_iterator >
const_item_iterator;
item_iterator Begin();
item_iterator End();
};
template<typename DstType,
typename Container = Container,
typename InputIterator = typename Container::iterator>
struct MagicIterator :
// pick either const T or T, depending on whether it's a const_iterator.
std::iterator<std::input_iterator_tag,
typename detail::constify<
DstType,
typename InputIterator::value_type*>::type> {
typedef std::iterator<std::input_iterator_tag,
typename detail::constify<
DstType,
typename InputIterator::value_type*>::type> base;
MagicIterator():wrapped() { }
explicit MagicIterator(InputIterator const& it):wrapped(it) { }
MagicIterator(MagicIterator const& that):wrapped(that.wrapped) { }
typename base::value_type operator*() {
return (*wrapped).pObject->GetInterface();
}
MagicIterator& operator++() {
++wrapped;
return *this;
}
MagicIterator operator++(int) {
MagicIterator it(*this);
wrapped++;
return it;
}
bool operator==(MagicIterator const& it) const {
return it.wrapped == wrapped;
}
bool operator!=(MagicIterator const& it) const {
return !(*this == it);
}
InputIterator wrapped;
};
// now that the iterator adepter is defined, we can define Begin and End
inline Container::item_iterator Container::Begin() {
return item_iterator(m_items.begin());
}
inline Container::item_iterator Container::End() {
return item_iterator(m_items.end());
}
Now, start using it:
for(MagicIterator<IInterface*> it = c.Begin(); it != c.End(); ++it) {
// ...
}
You can also use a iterator mixin provided by boost, which works like the input version of boost::function_output_iterator. It calls your iterator's operator() which then returns the appropriate value, doing what we do above in our operator* in principle. You find it in random/detail/iterator_mixin.hpp. That would probably result in fewer code. But it also requires to wrack up our neck to ensure the friend-stuff because Item is private and the iterator isn't defined inside Item. Anyway, good luck :)
It really depends on the Container, because the return values of c.Begin() and c.End() are implementation-defined.
If a list of possible Containers is known to MagicIterator, a wrapper class could be used.
template<typename T>
class MagicIterator
{
public:
MagicIterator(std::vector<T>::const_iterator i)
{
vector_const_iterator = i;
}
// Reimplement similarly for more types.
MagicIterator(std::vector<T>::iterator i);
MagicIterator(std::list<T>::const_iterator i);
MagicIterator(std::list<T>::iterator i);
// Reimplement operators here...
private:
std::vector<T>::const_iterator vector_const_iterator;
std::vector<T>::iterator vector_iterator;
std::list<T>::const_iterator list_const_iterator;
std::list<T>::iterator list_iterator;
};
The easy way would be to use a template which accepts Container's type:
// C++0x
template<typename T>
class Iterator :
public T::iterator
{
using T::iterator::iterator;
};
for(Iterator<Container> i = c.begin(); i != c.end(); ++i)
{
// ...
}
More information here.
I see no reason why you can't implement this exactly as you've laid it out... am I missing something?
To clarify, you'll need to put some kind of accessor methods on your Container class. They can be private and you can declare MagicIterator as a friend, if you feel that's the best way to encapsulate it, but I'd expose them directly. These accessor methods would use a normal STL iterator inside Container and perform the conversion to IInterface. Thus the iterating would actually be done with the Container's accessor methods and MagicIterator would just be a kind of proxy object to make it easier. To make it reentrant, you could have the MagicIterator pass in some kind of ID to look up the STL iterator inside Container, or you could actually have it pass in the STL iterator as a void *.
I've now found a solution which is fitter for my original purpose. I still don't like it though :)
The solution involves MagicIterator being templated on IInterface* and being constructed with both a void* to an iterator, the byte size of said iterator, and a table of pointers to functions which perform standard iteration functions on said void* such as increment, decrement, dereference, etc. MagicIterator assumes that it is safe to memcpy the given iterator into an internal buffer, and implements its own members by passing its own buffer as a void* to the supplied functions as if it were the original iterator.
Container then has to implement static iteration functions which cast back a supplied void* to a std::list::iterator. Container::begin() and Container::end() simply construct a std::list::iterator, pass a pointer to it into a MagicIterator along with a table of its iteration functions, and return the MagicIterator.
It's somewhat disgusting, and breaks my original rule regarding "no memcpy()", and makes assumptions about the internals of the iterators in question. But it avoids heap allocation, keeps Collection's internals (including Item) private, renders MagicIterator entirely independent of the collection in question and of IInterface*, and in theory allows MagicIterators to work with any collection (provided its iterators can be safely memcopy()'d).
A visitor may be a simpler (and therefore easier to maintain) solution.