Question

I am attempting to imitate the way STL iterators are declared by using inheritance and nested classes.

I have a parent class Iterable with nested class iterator.

class Iterable
{
public:
    class iterator
    { };
};

I have two classes, List and Vector, which inherit from Iterable in order to gain the nested class iterator.

class List : public Iterable
{ };

class Vector : public Iterable
{ };

This allows declaration of iterators like this.

   List::iterator lIte;
   Vector::iterator vIte;

However I would like to have compile time errors when attempting to mix iterators from different derived classes. E.g.

lIte = vIte; // throw a compile error

But, since the iterators come from the same base class, Iterable, the statement above will compile just fine.

An example work around would be to define a new nested class iterator which will inherit from Iterable::iterator in each class that inherits from Iterable (List and Vector). E.g.

class List : public Iterable
{
public:
    class iterator : Iterable::iterator // This "specializes" the datatype of iterator
    { };
};

class Vector : public Iterable
{
public:
    class iterator : Iterable::iterator
    { };  
};

Doing the above will successfully cause a compile time error when attempting:

   List::iterator lIte;
   Vector::iterator vIte;
   lIte = vIte;

However this is a sub-optimal work around as:

  1. It involves code duplication in every class that inherits from Iterable.
  2. It requires C++11 in order for the duplicated iterator classes to inherit appropriate constructors from Iterable::iterator.

My question is, how can I make List::iterator and Vector::iterator different types without duplicating code or using C++11 constructor inheritance?

Was it helpful?

Solution

You can use a class template to generate different classes from one common - well template:

template<typename T>
struct Iterable
{
    class iterator
    { };
};

class List : public Iterable<List>
{ };

class Vector : public Iterable<Vector>
{ };

However, while this solves your immediate problem, it does not look like a proper solution.
In fact, it does not really make sense to give Iterable an iterator class at all, unless it is a (potentially polymorphic) base class. After all, iterating over a vector works differently from iterating over an list.

Since you wish to imitate the C++ standard library, you should be aware that ::std::list and ::std::vector do not share any public base classes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top