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.
Related
I'm trying to use boost::circular_buffer to manage fixed size of the queue.
To do that, I wrap boost::circular_buffer by using class Something.
class Something {
public:
Something();
private:
boost::circular_buffer<int> buffer;
};
Here, the problem is that class Something should wrap iterator of buffer.
For example, If I use std::vector<int>, it is simple:
class Something {
public:
Something();
typedef std::vector<int>::iterator Iterator;
Iterator begin() { return buffer.begin(); }
Iterator end() { return buffer.end(); }
...
private:
std::vector<int> buffer;
};
How to use boost::circular_buffer to handle this?
If all you need is begin and end, you can simply use auto return type
(or decltype(auto) for general case)
class Something {
public:
Something();
auto begin() { return buffer.begin(); }
auto end() { return buffer.end(); }
private:
boost::circular_buffer<int> buffer;
};
You can do the exact same thing as you do with the std::vector.
typedef std::vector<int>::iterator Iterator; declares a local type called Iterator that is an alias for std::vector<int>'s iterator type.
So logically, you should be able to just swap out the std::vector<int> for a boost::circular_buffer<int> and it should just drop in:
#include <boost/circular_buffer.hpp>
class Something {
public:
Something();
typedef boost::circular_buffer<int>::iterator Iterator;
Iterator begin() { return buffer.begin(); }
Iterator end() { return buffer.end(); }
private:
boost::circular_buffer<int> buffer;
};
You can clean this up further a bit by using a second type alias for the container itself. This way, you can change the container type by altering a single line of code, and everything else flows from there.
#include <boost/circular_buffer.hpp>
class Something {
public:
Something();
using container_type = boost::circular_buffer<int>;
using iterator = container_type::iterator;
iterator begin() { return buffer.begin(); }
iterator end() { return buffer.end(); }
private:
container_type buffer;
};
N.B. I used using instead of typedef since it's generally considered easier to read in modern code, but the meaning is the same.
I'm trying to create my own translator. It's university work. I need an iterator in my class Translator.
class Translator
{
private:
map <string,Word> translator;
public:
class iterator
{
friend class Translator;
private:
map<string,Word>::iterator itm;
public:
iterator operator++();
pair <string,Word> &operator*();
bool operator==(const iterator &it)const;
};
};
I'm trying to overload operator*();
This is the code.
pair <string, Word>& Translator::iterator::operator*()
{
return (*itm);
}
Error:
invalid initialization of reference of type ‘std::pair<std::basic_string<char>, Word>&’ from expression of type ‘std::pair<const std::basic_string<char>, Word>
The keys of a map are constant, so the value type is pair<const string, Word>.
Some type aliases might make the code friendlier:
typedef map <string,Word> map_type;
typedef map_type::value_type value_type;
value_type &operator*();
It is more a complement than an actual answer but if you want a nice iterator (STL complient) you will also need to add several typedefs, to say for instance the type of your iterator (in your case you have an input iterator). Then you can use your iterator with any stl algorithm which can be very nice. However this can be quite cumbersome.
A very nice approach is using boost facade iterators, you just need to rewrite what is needed that is three methods for an input iterator that specify how to increment, test if two iterators are equals and dereference. Boost is then doing all the dirty work for you and you can then use all stl algorithms with your standard compliant iterators.
Here is an example from the link I gave you :
# include <boost/iterator/iterator_facade.hpp>
# include "node.hpp"
class node_iterator : public boost::iterator_facade<
node_iterator
, node_base
, boost::forward_traversal_tag
>{
public:
node_iterator()
: m_node(0) {}
explicit node_iterator(node_base* p)
: m_node(p) {}
private:
friend class boost::iterator_core_access;
void increment() { m_node = m_node->next(); }
bool equal(node_iterator const& other) const
{
return this->m_node == other.m_node;
}
node_base& dereference() const { return *m_node; }
node_base* m_node;
};
I have a Red Black tree implemented in c++. It supports the functionality of a STL map. Tree nodes contain keys and the values mapped. I want to write an iterator class for this, but I'm stuck with how to do it. Should I make it an inner class of the Tree class? Can anyone give me some guidelines on how to write it + some resources??
Thank You!!
Sure, read this nice article on writing STL iterators, it might give you the needed overview:
http://www.drdobbs.com/184401417
In general, yes, an inner class is good, because the iterator needs access to your implementation specific tree nodes:
struct container { ...
public:
struct iterator {
// these typedefs are needed if you want to be STL compatible
typedef std::forward_iterator_tag iterator_category;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
// the element points to your implementation node
iterator( element* init = 0 ) : current(init) {}
T& operator*() { return current->data; } // dereference
const T& operator*() const { return current->data; }
iterator& operator++() { // prefix
if ( current ) current = current->next;
return *this;
}
iterator operator++(int) { // postfix
iterator temp = *this;
++*this;
return temp;
}
bool operator==(const iterator& x) const { return current == x.current; }
bool operator!=(const iterator& x) const { return current != x.current; }
private:
// the element points to your implementation node
element* current;
}
...
The good thing here is that while the iterator is public, the element can still stay private :). And yes, the code above is STL compilant too!
I thought I would add my own little batch of advice.
The first thing I'd like to note is that iterator and const_iterator are very likely to have much of their implementation in common. However, even though their code is similar, it's not exactly identical. This begs for templates.
The second thing I'd like to note is that a const_iterator should be constructible from an iterator (implicitly), but not the other way around.
The third thing I'd like to note is that if you wish to have a map-like interface, then you need to provide a reverse_iterator and const_reverse_iterator as well.
From a style point of view, I tend not to put the implementation of the iterator itself right in the class. I find it unreadable when the class implementation is cluttered with so much code that you struggle to see the types and methods available. For this reason I would recommend putting the implementation outside the class.
Finally, I definitely recommend Boost.Iterator. You may not use it, but read the material, it'll notably give you insight on how to write the code once and use it for the 4 kinds!
Quick illustration:
namespace detail {
template <class Value> class base_iterator;
}
template <class Value>
class container
{
public:
typedef detail::base_iterator<Value> iterator;
typedef detail::base_iterator<Value const> const_iterator;
typedef boost::reverse_iterator<iterator> reverse_iterator;
typedef boost::reverse_iterator<const_iterator> const_reverse_iterator;
};
I don't know about you, but I feel good when I do only a quarter of the work and leverages a compiler/library to fill in the rest for me :)
The iterator class needs to be either a nested class, or at least a typedef that aliases your_map::iterator to some type that's defined elsewhere. A nested class is usually the cleanest/easiest route though.
As far as resources go, one possible source of help would be the Boost::iterator library, which includes components intended to make iterators easier to implement.
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.