Custom container range-based iteration - c++

I have a custom container which I want to use in a ranged-based for loop. The container is somewhat based on a vector, like this:
template<typename T>
class IDMap
{
private:
struct Item {
uint16_t mVersion;
T mItem;
template <typename... Arguments>
Item(uint16_t version, Arguments&&... args) : mVersion(version), mItem(args...)
{
}
};
public:
typedef uint32_t ItemID;
template <typename... Arguments>
ItemID AddItem(Arguments&&... args);
void MarkAsFree(const ItemID id);
T& GetItem(const ItemID id);
T* TryGetItem(const ItemID id);
void Clear();
private:
std::vector<Item> mItems;
std::vector<uint16_t> mFreeIndices;
};
I want to iterate the mItems vector, but only return the mItem member rather than the entire Item struct. Is there any easy/elegant way to do this?

You have to provide a begin and end function, both returning a corresponding iterator, which itself implements operators ++, != and *. The begin and end functions can be free-standing or as members.
Start with implementing an iterator which has the behavior you want. You can implement it as a wrapper around a std::vector::iterator to save most of the "core" work.
The following is untested code
Basically, inside class IDMap, add:
class ItemIterator {
// based on vector iterator
std::vector<Item>::iterator i;
public:
ItemIterator(std::vector<Item>::iterator i) : i(i) {}
// incrementing
ItemIterator & operator ++() { ++i; return *this; }
ItemIterator operator ++(int) { const_iterator old(*this); ++(*this); return old; }
// comparison
bool operator!=(const ItemIterator &o) const { return i != o.i; }
// dereferencing
const T & operator*() const { return i->mItem; }
};
using iterator = ItemIterator;
using value_type = T;
ItemIterator begin() const { return ItemIterator(mItems.begin()); }
ItemIterator end() const { return ItemIterator(mItems.end() ); }
If you ever want to support multiple kinds of "special iteration" over your IDMap, like for example also over the indices, or over the "whole" Items, you should wrap everything above in another adaptor. This adaptor can then be accessed with a member method, like .items().
Brief example:
class IDMap {
// (your code)
public:
struct ItemsAdaptor {
// (insert above iterator definition + usings)
ItemsAdaptor(std::vector<Item>::iterator b,
std::vector<Item>::iterator e)
: b{b}, e{e}
{}
ItemIterator begin() const { return b; }
ItemIterator end() const { return e; }
private:
ItemIterator b, e;
};
ItemsAdaptor items() const {
return ItemsAdaptor(mItems.begin(), mItems.end());
}
};
Then, you can write:
IDMap<int> map = ...;
for (int i : map.items()) {
...
}

If you want the range-based for to work for your container, you have to provide begin and end functions that return forward iterators.
typedef std::vector<Item>::iterator iterator;
typedef std::vector<Item>::const_iterator const_iterator;
iterator begin()
{
return mItems.begin();
}
const_iterator begin() const;
{
return mItems.begin();
}
//also add end functions, and viola.
This will return the whole item struct. If you have to only return mItem, you'll have to write your own iterator adaptor and use it instead of vector's.

Related

No known conversions

I'm have a problem with my constructors.
I get the following error:
no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >*’ to ‘std::multiset<std::__cxx11::basic_string<char> >::iterator {aka std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >}’
multiset.cpp:47:1: note: candidate: my_multiset::iterator::iterator()
my_multiset::iterator::iterator(void){}
multiset.h:17:10: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >*’ to ‘const cpt323::my_multiset::iterator&’
multiset.h:17:10: note: candidate: constexpr my_multiset::iterator::iterator(cpt323::my_multiset::iterator&&)
multiset.h:17:10: note: no known conversion for argument 1 from ‘std::_Rb_tree_const_iterator<std::__cxx11::basic_string<char> >*’ to ‘my_multiset::iterator&&’
The code is working with the exception of this part, any suggestion on how to make the appropriate changes
class my_multiset : custom_datastructure
{
std::multiset<std::string> the_set;
std::multiset<std::string>::iterator head;
std::multiset<std::string>::iterator tail;
public:
class iterator : public custom_datastructure::iterator
{
std::multiset<std::string>::iterator current;
public:
iterator(void){};
iterator(std::multiset<std::string>::iterator a_set) : current(a_set)
{
}
};
multiset(void);
std::unique_ptr<custom_datastructure::iterator> begin(void)
{
head = the_set.begin();
return std::make_unique<my_multiset::iterator>(&head);
}
std::unique_ptr<custom_datastructure::iterator> end(void)
{
tail = the_set.end();
return std::make_unique<my_multiset::iterator>(&tail);
}
}
custom_datastructure is as below
struct datastructure
{
struct iterator
{
/** OPERATORS HERE **/
virtual std::unique_ptr<datastructure::iterator> operator++(void) = 0;
/** ETC **/
};
virtual std::unique_ptr<iterator> begin(void) = 0;
virtual std::unique_ptr<iterator> end(void) = 0;
}
Why is your code breaking?
The reason your code breaks is because unique_ptr can't be used as an iterator, so if you wrap your iterator in a unique_ptr when returning it from begin() and end(), then it isn't usable as an iterator anymore.
An iterator doesn't have to be a pointer; it just needs to act like one. In addition, an iterator shouldn't own data. A class owns data if the class is responsible for deleting that data, but an iterator shouldn't be responsible for deleting anything. It should just provide a way of accessing the data. This means that iterators can and should be passed around by value (instead of using std::unique_ptr).
How do we fix the design?
So here's the big question: are you trying to create an interface that returns some iterators, or are you trying to create an interface for things that act like iterators?
Creating an interface that returns some iterators
The most generic way to do this is through templates. The benefit of using templates is that it enables us to re-use this interface in a wide variety of situations, and we can #include the interface where we need it, without having any dependencies in the file defining the template.
template<class Iterator>
class Iterable {
public:
virtual Iterator begin() = 0;
virtual Iterator end() = 0;
};
We can use this to define my_multiset as returning iterators to std::multiset:
class my_multiset
: public Iterable<typename std::multiset<std::string>::iterator>
{
std::multiset<std::string> the_set;
public:
using iterator = typename std::multiset<std::string>::iterator;
iterator begin() override {
return the_set.begin();
}
iterator end() override {
return the_set.end();
}
};
Creating a GenericIterator<Value> - a class that can be assigned any iterator
Because pointers-to-iterators act like pointers, and not the underlying iterator, instead of using a unique_ptr<BaseIterator>, we're going to want to create a wrapper class that handles everything for us, while still acting like a normal iterator.
You'll be able to use it just like any old iterator, except that it can be assigned or created with an iterator to anything that derefences to Value. That means that the same GenericIterator can bind to a list iterator, a vector iterator, or even a std::multiset iterator.
Example showing how it could be used:
#include <iostream>
#include <list>
#include <vector>
int main()
{
std::vector<int> v{1, 2, 3};
std::list<int> l{10, 20, 30};
GenericIterator<int&> begin, end;
begin = v.begin();
end = v.end();
for (; begin != end; ++begin)
{
std::cout << *begin << " ";
}
begin = l.begin();
end = l.end();
for (; begin != end; ++begin)
{
std::cout << *begin << " ";
}
}
What parts do we need to make GenericIterator?
GenericIterator is going to store a pointer to a virtual base class. We'll also need a derived class that implements the base for a specific Iter.
Base class:
The base class virtualizes the main functions of an iterator: Increment, Dereference, and equality. It also provides a clone() method so that it's possible to make copies of iterators. close() comes in handy when writing a GenericIterator class that wraps this functionality.
template <class Value>
class IteratorBase
{
public:
virtual Value operator*() const = 0;
virtual IteratorBase& operator++() = 0;
virtual bool operator!=(IteratorBase const&) const = 0;
virtual bool operator==(IteratorBase const&) const = 0;
// We need this function for making copies of the iterator
virtual IteratorBase* clone() const = 0;
virtual ~IteratorBase() = default;
};
Derived class:
This derived class can wrap basically any other iterator on the planet, and it overrides all the methods in IteratorBase to give a fully-functioning iterator.
template <class Iter, class Value>
class IteratorDerived : public IteratorBase<Value>
{
Iter it;
public:
IteratorDerived() = default;
IteratorDerived(Iter it) : it(it) {}
IteratorDerived(IteratorDerived const&) = default;
IteratorDerived(IteratorDerived&&) = default;
Value operator*() const override { return *it; }
IteratorBase<Value>& operator++() override
{
++it;
return *this;
}
bool operator!=(IteratorBase<Value> const& other) const override
{
auto* derived = dynamic_cast<IteratorDerived const*>(&other);
return derived == nullptr || it != derived->it;
}
bool operator==(IteratorBase<Value> const& other) const override
{
auto* derived = dynamic_cast<IteratorDerived const*>(&other);
return derived != nullptr && it == derived->it;
}
IteratorBase<Value>* clone() const override
{
return new IteratorDerived(*this);
}
};
Generic Wrapper:
This GenericWrapper encapsulates all the functionality of an iterator, and because of how we're writing it, you can automatically assign any iterator that deferences to a matching value type.
template <class Value>
class GenericIterator
{
std::unique_ptr<IteratorBase<Value>> iterator;
public:
GenericIterator() = default;
GenericIterator(GenericIterator const& it) : iterator(it.iterator->clone())
{
}
GenericIterator(GenericIterator&&) = default;
// Creates a GenericIterator from an IteratorBase
explicit GenericIterator(IteratorBase<Value> const& it)
: iterator(it.clone())
{
}
// Creates a GenericIterator from an IteratorDerived
template <class Iter>
explicit GenericIterator(IteratorDerived<Iter, Value> const& it)
: iterator(it.clone())
{
}
// Creates a GenericIterator by wrapping another Iter
template <class Iter>
GenericIterator(Iter it) : iterator(new IteratorDerived<Iter, Value>(it))
{
}
GenericIterator& operator=(GenericIterator const& it)
{
iterator = std::unique_ptr<IteratorBase<Value>>(it.iterator->clone());
return *this;
}
GenericIterator& operator=(GenericIterator&&) = default;
Value operator*() const { return *(*iterator); }
GenericIterator& operator++()
{
++(*iterator);
return *this;
}
bool operator==(GenericIterator const& other) const
{
return *iterator == *other.iterator;
}
bool operator!=(GenericIterator const& other) const
{
return *iterator != *other.iterator;
}
};
Optional: C++17 template deduction guide
We can write a template type deduction guide for GenericIterator that automatically fills in the correct template parameter, making it easy to wrap any other iterator.
template<class Iter>
GenericIterator(Iter) -> GenericIterator<decltype(*std::declval<Iter>())>;

C++ confused with partial template specialization syntax

Is there a way I could avoid using Range2 as a name and have both classes named Range? I'm a bit confused with the C++ template syntax.
template <int BEGIN, int END>
class Range2
{
public:
class Iterator
{
private:
int n;
public:
Iterator(int n)
: n(n)
{
}
int operator *() const
{
return n;
}
Iterator const & operator ++()
{
++n;
return *this;
}
bool operator !=(Iterator const & i) const
{
return n != i.n;
}
};
Iterator begin() const
{
return Iterator(BEGIN);
}
Iterator end() const
{
return Iterator(END);
}
};
template<int END>
class Range
: public Range2<0, END>
{
};
As with function arguments, in C++ template arguments can have a default value. The only thing you will have to pay for this putting the END, which has no default value, before the BEGIN, which has 0 as default.
// Here we add the default parameter to BEGIN
// The arguments are switched because END is without a default
// parameter, so it has to come before BEGIN that has one
template <int END, int BEGIN=0>
// The class itself is the same, but now you can use it
// without giving a BEGIN parameters
class Range
{
public:
class Iterator
{
private:
int n;
public:
Iterator(int n)
: n(n)
{
}
int operator *() const
{
return n;
}
Iterator const & operator ++()
{
++n;
return *this;
}
bool operator !=(Iterator const & i) const
{
return n != i.n;
}
};
Iterator begin() const
{
return Iterator(BEGIN);
}
Iterator end() const
{
return Iterator(END);
}
};
It compiles and should work as intended. Without a main, I wasn't able to test it, though.
EDIT: I added some comments and here an example of usage, just for clarity:
Range<10, 3> r(3); /*here we use it as usual, pay attention begin is
now the second argument and not the first */
Range<10> r(0); /* here we don't give a BEGIN argument, the
compiler will use the default one */

Iterator for multi-dimensional vector that is used as unidimensional?

I have a vector that looks like this:
std::vector<std::vector<MyClass>> myVector;
And I would like to access its elements through iterators as if it was an unidimensional vector:
for (auto& x : myVector)
{
foo(x); // x is an object of type MyClass
}
(i.e. the fact that there are multiple dimensions is transparent to whoever loops through myVector)
I have an idea of how this should be done, have a custom iterator implementation that saves current indexes so that when one of the vectors has no more elements, it resets one of the indexes and increments the other so that it can start iterating through the next vector and so on. But I have been trying to code this idea but can't seem to get this working. Does anyone have any idea of how I can possibly achieve this? Or even better, if there's any open-source project that has a similar implementation?
Thanks.
It's totally possible to define your own iterator to hide all the details of iterating through a vector of vector, I wrote some code to give you the idea, mind that it should require more checks but it basically works and give you the idea.
You just need to write the required operations to make it work in other code like an opaque iterator.
template <typename T>
struct vector2d
{
public:
class iterator
{
public:
using vector_type = std::vector<std::vector<T>>;
using first_level_iterator = typename std::vector<std::vector<T>>::iterator;
using second_level_iterator = typename std::vector<T>::iterator;
private:
vector_type& data;
first_level_iterator fit;
second_level_iterator sit;
public:
iterator(vector_type& data, bool begin) : data(data)
{
if (begin)
{
fit = data.begin();
sit = fit->begin();
}
else
{
fit = data.end();
}
}
inline bool operator!=(const iterator& other) const { return fit != other.fit || (fit != data.end() && sit != other.sit); }
inline const iterator& operator++() {
// don't go past end
if (fit == data.end())
return *this;
// increment inner iterator
++sit;
// if we reached the end of inner vector
if (sit == fit->end())
{
// go to next vector
++fit;
// if we reached end then don't reset sit since it would be UB
if (fit != data.end())
sit = fit->begin();
}
return *this;
}
T& operator*() const { return *sit; }
};
public:
std::vector<std::vector<T>> data;
iterator begin() { return iterator(this->data, true); }
iterator end() { return iterator(this->data, false); }
};
A small test:
int main() {
vector2d<int> data;
data.data.push_back(vector<int>());
data.data.push_back(vector<int>());
data.data.push_back(vector<int>());
for (int i = 1; i < 5; ++i)
{
data.data[0].push_back(i);
data.data[1].push_back(i*2);
data.data[2].push_back(i*3);
}
for (auto i : data)
{
cout << i << endl;
}
return 0;
}
The behavior is rather simple but you must make sure that it's always consistent for all the edge cases.
A pretty minimal range type:
template<class It>
struct range_t {
private:
It b, e;
public:
It begin() const { return b; }
It end() const { return e; }
decltype(auto) front() const { return *b; }
decltype(auto) back() const { return *std::prev(e); }
bool empty() const { return b==e; }
range_t without_front( std::size_t n = 1 ) const {
auto r = *this;
std::advance(r.b,n);
return r;
}
range_t without_back( std::size_t n = 1 ) const {
auto r = *this;
std::advance(r.e,std::ptrdiff_t(-n));
return r;
}
range_t(It s, It f):b(std::move(s)), e(std::move(f)) {}
range_t():b(), e() {}
};
template<class It>
range_t<It> range( It b, It e ) {
return {std::move(b), std::move(e)};
}
Doing this task is far easier with ranges than with iterators.
template<class Outer, class Inner>
struct stacked_range_t {
range_t<Outer> outer;
stacked_range_t()=default;
stacked_range_t( range_t<Outer> o ):outer(std::move(o)) {}
struct iterator {
private:
range_t<Outer> outer;
range_t<Inner> inner;
public:
iterator(
range_t<Outer> o,
range_t<Inner> i
):outer(std::move(o)), inner(std::move(i)) {}
iterator()=default;
friend auto mytie(iterator const& it) {
return std::tie( it.outer.begin(), it.inner.begin(), it.inner.end() );
}
friend bool operator==(iterator const& lhs, iterator const& rhs) {
return mytie(lhs)==mytie(rhs);
}
friend bool operator!=(iterator const& lhs, iterator const& rhs) {
return mytie(lhs)==mytie(rhs);
}
using difference_type = std::ptrdiff_t;
using value_type = typename std::iterator_traits<Inner>::value_type;
using pointer = typename std::iterator_traits<Inner>::pointer;
using reference = typename std::iterator_traits<Inner>::reference;
using iterator_category = std::input_iterator_tag;
reference operator*() const {
return *inner.begin();
}
pointer operator->() const {
return inner.begin().operator->();
}
iterator& operator++() {
using std::begin; using std::end;
inner = inner.without_front();
while (inner.empty())
{
outer = outer.without_front();
if (!outer.empty())
inner = range( begin(outer.front()), end(outer.front()) );
}
return *this;
}
iterator operator++(int) {
auto it = *this;
++*this;
return it;
}
};
iterator end() const {
return { range( outer.end(), outer.end() ), {} };
}
// a bit tricky:
iterator begin() const {
if (outer.empty()) return end();
auto rout = outer;
while( !rout.empty() ) {
using std::begin; using std::end;
auto rin = range( begin(rout.front()), end(rout.front()) );
if (!rin.empty())
return {std::move(rout), std::move(rin)};
rout = rout.without_front();
}
return end();
}
};
and a function to create it:
template<class Range>
auto make_stacked_range(Range& r) {
using std::begin; using std::end;
using Outer = decltype(begin(r));
using Inner = decltype(begin(*begin(r));
return stacked_range_t<Outer, Inner>{
{begin(r), end(r)}
};
}
there probably are typos. Use of C++1z features can be worked around with overly annoying decltype expressions and helper traits classes.
Relies on the iterators being trivially constructible, and such trivially constructed iterators are equal.
try to use template recursion,e.g.:
#include <stdio.h>
#include <vector>
template <typename V>
void f(V& v){
for(auto& e : v){
f(e);
}
printf("\n");
}
template <>
void f(int& v){
printf("%d ",v);
}
int main(){
std::vector<int> v1={1,2};
f(v1);
std::vector<std::vector<int> > v2={{3,4},{5,6,7}};
f(v2);
return 0;
};
With range/v3:
for (auto& x : myVector | ranges::view::join)
{
foo(x); // x is an object of type MyClass&
}
Demo

How to provide stl like container with public const iterator and private non-const iterator?

I have a class that includes a std::list and wish to provide public begin() and end() for const_iterator and private begin() and end() for just plain iterator.
However, the compiler is seeing the private version and complaining that it is private instead of using the public const version.
I understand that C++ will not overload on return type (in this case const_iterator and iterator) and thus it is choosing the non-const version since my object is not const.
Short of casting my object to const before calling begin() or not overloading the name begin is there a way to accomplish this?
I would think this is a known pattern that folks have solved before and would like to follow suit as to how this is typically solved.
class myObject {
public:
void doSomethingConst() const;
};
class myContainer {
public:
typedef std::list<myObject>::const_iterator const_iterator;
private:
typedef std::list<myObject>::iterator iterator;
public:
const_iterator begin() const { return _data.begin(); }
const_iterator end() const { return _data.end(); }
void reorder();
private:
iterator begin() { return _data.begin(); }
iterator end() { return _data.end(); }
private:
std::list<myObject> _data;
};
void myFunction(myContainer &container) {
myContainer::const_iterator itr = container.begin();
myContainer::const_iterator endItr = container.end();
for (; itr != endItr; ++itr) {
const myObject &item = *itr;
item.doSomethingConst();
}
container.reorder(); // Do something non-const on container itself.
}
The error from the compiler is something like this:
../../src/example.h:447: error: `std::_List_iterator<myObject> myContainer::begin()' is private
caller.cpp:2393: error: within this context
../../src/example.h:450: error: `std::_List_iterator<myObject> myContainer::end()' is private
caller.cpp:2394: error: within this context
Thanks.
-William
Bad idea to derive from std::list (it is not designed to be derived from).
Use a member variable of type std::list.
class myContainer
{
std::list<myObject> m_data;
public:
typedef std::list<myObject>::const_iterator myContainer::const_iterator;
private:
typedef std::list<myObject>::iterator myContainer::iterator;
public:
myContainer::const_iterator begin() const
{
return m_data.begin();
}
myContainer::const_iterator end() const
{
return m_data.end();
}
private:
myContainer::iterator begin()
{
return m_data.begin();
}
myContainer::iterator end()
{
return m_data.end();
}
};
I think your only option is to rename the private methods (if you need them in the first place).
In addition I believe you should rename the typedefs:
class MyContainer
{
public:
typedef std::list<Object>::const_iterator iterator;
typedef iterator const_iterator;
const_iterator begin() const;
const_iterator end() const;
private:
typedef std::list<Object>::iterator _iterator;
_iterator _begin();
_iterator _end();
...
};
Containers are supposed to typedef both iterator and const_iterator. A generic function accepting a non-const instance of your container might expect to make use of the iterator typedef - even if it is not going to modify the elements. (For example BOOST_FOREACH.)
It will be fine as far as const correctness goes, because should the generic function actually try to modify the objects, the real iterator type (being a const_iterator) wouldn't let it.
As a test, the following should compile with your container:
int main()
{
myContainer m;
BOOST_FOREACH(const myObject& o, m)
{}
}
Note that m is not const, but we are only trying to obtain const references to the contained types, so this should be allowed.
You need to change the name of the private begin end. The compiler can't differentiate by only the return type
This works for me : note the _begin _end names
#include <list>
class myObject {};
class myContainer : private std::list<myObject> {
public:
typedef std::list<myObject>::const_iterator const_iterator;
private:
typedef std::list<myObject>::iterator iterator;
public:
myContainer::const_iterator begin() const {
return std::list<myObject>::begin();
}
myContainer::const_iterator end() const {
return std::list<myObject>::end();
}
private:
myContainer::iterator _begin() {
return std::list<myObject>::begin();
}
myContainer::iterator _end() {
return std::list<myObject>::end();
}
};
void myFunction(myContainer &container) {
myContainer::const_iterator aItr = container.begin();
myContainer::const_iterator aEndItr = container.end();
for (; aItr != aEndItr; ++aItr) {
const myObject &item = *aItr;
// Do something const on container's contents.
}
}
int main(){
myContainer m;
myFunction(m);
}
You might want to change the signature of your method Myfunction to this:
void myFunction(const myContainer &container)
because a const method would be called on a const object only. What currently is happening is that you are trying to call a non-const method which in your case is private.

How to create an iterator over elements that match a derived type in C++?

I'd like an iterator in C++ that can only iterate over elements of a specific type. In the following example, I want to iterate only on elements that are SubType instances.
vector<Type*> the_vector;
the_vector.push_back(new Type(1));
the_vector.push_back(new SubType(2)); //SubType derives from Type
the_vector.push_back(new Type(3));
the_vector.push_back(new SubType(4));
vector<Type*>::iterator the_iterator; //***This line needs to change***
the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
SubType* item = (SubType*)*the_iterator;
//only SubType(2) and SubType(4) should be in this loop.
++the_iterator;
}
How would I create this iterator in C++?
boost filter iterator?
You must use a dynamic cast.
the_iterator = the_vector.begin();
while( the_iterator != the_vector.end() ) {
SubType* item = dynamic_cast<SubType*>(*the_iterator);
if( item != 0 )
...
//only SubType(2) and SubType(4) should be in this loop.
++the_iterator;
}
Solution without boost. But if you have an access to the boost library - use Filter Iterator as was proposed.
template <typename TCollection, typename T>
class Iterator
{
public:
typedef typename TCollection::iterator iterator;
typedef typename TCollection::value_type value_type;
Iterator(const TCollection& collection,
iterator it):
collection_(collection),
it_(it)
{
moveToNextAppropriatePosition(it_);
}
bool operator != ( const Iterator& rhs )
{
return rhs.it_ != it_;
}
Iterator& operator++()
{
++it_;
moveToNextAppropriatePosition(it_);
return *this;
}
Iterator& operator++(int);
Iterator& operator--();
Iterator& operator--(int);
value_type& operator*()
{
return *it_;
}
value_type* operator->()
{
return &it_;
}
private:
const TCollection& collection_;
iterator it_;
void moveToNextAppropriatePosition(iterator& it)
{
while ( dynamic_cast<T*>(*it) == NULL && it != collection_.end() )
++it;
}
};
class A
{
public:
A(){}
virtual ~A(){}
virtual void action()
{
std::cout << "A";
}
};
class B: public A
{
public:
virtual void action()
{
std::cout << "B";
}
};
int main()
{
typedef std::vector< A* > Collection;
Collection c;
c.push_back( new A );
c.push_back( new B );
c.push_back( new A );
typedef Iterator<Collection, B> CollectionIterator;
CollectionIterator begin(c, c.begin());
CollectionIterator end(c, c.end());
std::for_each( begin, end, std::mem_fun(&A::action) );
}
As paintballbob said in a comment, you should create your own iterator class, perhaps inheriting from vector<Type*>::iterator. In particular, you will need to implement or override operator++() and operator++(int) to ensure that you skip non-SubType objects (you can use dynamic_cast<SubType*>() to check each item). There is a nice overview of implementing your own container and iterator in this O'Reilly Net article.
Just another way how to do it using boost iterators. This time, using std::remove_copy_if:
std::remove_copy_if(v.begin(), v.end(),
boost::make_function_output_iterator(boost::bind(&someFunction, _1)),
!boost::lambda::ll_dynamic_cast<SubType*>(boost::lambda::_1));
It will call a function (In this example someFunction. But it can be anything boost::bind can construct - also a member-function) for each pointer that's pointing to a SubType.