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 outsideContainer
.Container::Item
must remain private.
MagicIterator
has to iterate overIInterface
pointers, despite the fact thatContainer
holds astd::list<Container::Item>
.Container::Item
contains anObject*
, andObject
can be used to fetchIInterface*
.
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 withIInterface*
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 insideMagicIterator
(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()
ormalloc()
at any stage), and nomemcpy()
.
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.