C ++迭代器适配器,它包装和隐藏内部迭代器并转换迭代类型 [英] A C++ iterator adapter which wraps and hides an inner iterator and converts the iterated type

查看:141
本文介绍了C ++迭代器适配器,它包装和隐藏内部迭代器并转换迭代类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

玩弄了这个我怀疑这不是遥远的可能,但我想我会问专家。我有以下C ++代码:

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;
};

我想将这些方法添加到Container中:

I want to add these methods to Container:


    MagicIterator<IInterface*> Begin();
    MagicIterator<IInterface*> End();

为了呼叫者可以写:


Container c = [...]
for (MagicIterator<IInterface*> i = c.Begin(); i != c.End(); i++)
{
    IInterface* pItf = *i;
    [...]
}


$ b

因此,我想提供一个类似于迭代的类一些集合(其中Begin()和End()的调用者不允许看到)IInterface指针,但实际上是迭代到其他对象的指针集合(对Container类是私有的),可以转换为IInterface

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.

以下几个要点:


  • MagicIterator Container 之外定义。
  • Container :: Item 必须保持私有。
  • MagicIterator is to be defined outside Container.
  • Container::Item must remain private.

  • MagicIterator 必须迭代尽管事实上 Container 包含 std :: list< Container :: Item> ,但是IInterface $ c>。 Container :: Item 包含 Object * Object 可用于获取 IInterface *
  • 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 必须可以重复使用几个类,但是在内部可以具有不同的列表实现,其持有不同的对象( std :: vector< SomeOtherItem> mylist< YetAnotherItem> ),并且每次以不同的方式获得 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 不应包含特定于容器的代码,可以委托给这样做的类,只要这种委托不是硬编码到 MagicIterator 中的特定容器(例如由编译器自动解析)。
  • 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).

  • 解决方案必须在Visual C ++下编译,而不使用其他需要许可协议的库他们的作者。
  • The solution must compile under Visual C++ without use of other libraries (such as boost) which would require a license agreement from their authors.
  • 此外,迭代可能不会分配任何堆内存(因此 new() malloc()),并且没有 memcpy()
  • 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!

更新:虽然我有一些非常有趣的答案,但没有一个符合所有上述要求。特别是棘手的领域是i)解耦MagicIterator从容器不知何故(默认模板参数不剪切它),和ii)避免堆分配;

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've now found a solution which is fitter for my original purpose. I still don't like it though :)

解决方案涉及MagicIterator在IInterface *上模板化,并且使用void *到迭代器构造,字节大小所述迭代器,以及对所述void *执行标准迭代函数的函数的指针表,例如增量,减量,解引用等。MagicIterator假定将给定的迭代器memcpy到内部缓冲器中是安全的,并且实现它自己的成员通过将自己的缓冲区作为void *传递给提供的函数,就好像它是原始的迭代器一样。

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然后必须实现静态迭代函数, *到std :: list :: iterator。 Container :: begin()和Container :: end()只是构造一个std :: list :: iterator,将一个指针传递给一个MagicIterator以及它的迭代函数表,并返回MagicIterator。

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.

这有点令人厌恶,打破了我对no memcpy()的原始规则,并对所讨论的迭代器的内部做出了假设。但是它避免了堆分配,保持Collection的内部(包括Item)私有,使得MagicIterator完全独立于有问题的集合和IInterface *,并且在理论上允许MagicIterators使用任何集合(假设它的迭代器可以安全地memcopy() d)。

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).

这篇关于C ++迭代器适配器,它包装和隐藏内部迭代器并转换迭代类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆