I have a particular class that stores a piece of data, which implements an interface:
template
class MyContainer : public Container
I would suggest a look at the Visitor
pattern.
Other than that, what you want is a value type that will be imbued with polymorphic behavior. There is a much simpler solution than James' using your IInterface
.
class IInterface
{
virtual ~IInterface() {}
virtual void next() = 0;
virtual void previous() = 0;
virtual T* pointer() const = 0;
virtual std::unique_ptr clone() const = 0;
};
std::unique_ptr clone(std::unique_ptr const& rhs) {
if (!rhs) { return std::unique_ptr(); }
return rhs->clone();
}
class Iterator
{
friend class Container;
public:
Iterator(): _impl() {}
// Implement deep copy
Iterator(Iterator const& rhs): _impl(clone(rhs._impl)) {}
Iterator& operator=(Iterator rhs) { swap(*this, rhs); return *this; }
friend void swap(Iterator& lhs, Iterator& rhs) {
swap(lhs._impl, rhs._impl);
}
Iterator& operator++() { assert(_impl); _impl->next(); return *this; }
Iterator& operator--() { assert(_impl); _impl->previous(); return *this; }
Iterator operator++(int); // usual
Iterator operator--(int); // usual
T* operator->() const { assert(_impl); return _impl->pointer(); }
T& operator*() const { assert(_impl); return *_impl->pointer(); }
private:
Iterator(std::unique_ptr impl): _impl(impl) {}
std::unique_ptr _impl;
};
And finally, the Container
class will propose:
protected:
virtual std::unique_ptr make_begin() = 0;
virtual std::unique_ptr make_end() = 0;
And implement:
public:
Iterator begin() { return Iterator(make_begin()); }
Iteraotr end() { return Iterator(make_end()); }
Note:
You can do away with the std::unique_ptr
if you can avoid the ownership issue. If you can restrict the IInterface to be behavioral only (by extracting the state into Iterator
), then you can have the Strategy
pattern kick-in, and use a pointer a statically allocated object. This way, you avoid dynamic allocation of memory.
Of course, it means your iterators won't be so rich, as it requires IInterface
implementations to be stateless, and implementing "filtering" iterators, for example, would become impossible.