El *_*rko 15 c++ templates iterator adapter wrapper
玩弄了这个,我怀疑它不可能,但我想我会问专家.我有以下C++代码:
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:
MagicIterator<IInterface*> Begin(); MagicIterator<IInterface*> End();
为了让呼叫者可以写:
Container c = [...] for (MagicIterator<IInterface*> i = c.Begin(); i != c.End(); i++) { IInterface* pItf = *i; [...] }
所以基本上我想提供一个类似乎迭代某些集合(其中Begin()和End()的调用者不允许看到)的IInterface指针,但它实际上迭代了指向其他指针的指针集合.对象(Container类专用),可以转换为IInterface指针.
几个关键点:
MagicIterator
是在外面定义的Container
.
Container::Item
必须保持私密.
MagicIterator
有遍历IInterface
,指针尽管事实Container
持有std::list<Container::Item>
.Container::Item
包含一个Object*
,Object
可用于获取IInterface*
.
MagicIterator
必须可以重用几个类似于Container的类,但可能在内部有不同的列表实现std::vector<SomeOtherItem>
,每个时间以不同的方式保存不同的对象(,mylist<YetAnotherItem>
)IInterface*
.
MagicIterator
不应该包含特定于容器的代码,尽管它可以委托给那样做的类,只要这样的委托不是硬编码到内部的特定容器MagicIterator
(例如,由编译器以某种方式自动解析).
new()
或malloc()
在任何阶段),没有memcpy()
.
感谢您的时间,即使您只是在阅读; 这个人真的在烦我!
更新:虽然我有一些非常有趣的答案,但还没有一个满足上述所有要求.值得注意的是,棘手的领域是:i)以某种方式将MagicIterator与Container分离(默认模板参数不会削减它),以及ii)避免堆分配; 但我真的想要一个涵盖所有上述子弹的解决方案.
jpa*_*cek 15
我认为你有两个不同的问题:
首先,创建一个迭代器,它将返回IInterface*
你的list<Container::Item>
.这很容易完成boost::iterator_adaptor
:
class cont_iter
: public boost::iterator_adaptor<
cont_iter // Derived
, std::list<Container::Item>::iterator // Base
, IInterface* // Value
, boost::forward_traversal_tag // CategoryOrTraversal
, IInterface* // Reference :)
>
{
public:
cont_iter()
: cont_iter::iterator_adaptor_() {}
explicit cont_iter(const cont_iter::iterator_adaptor_::base_type& p)
: cont_iter::iterator_adaptor_(p) {}
private:
friend class boost::iterator_core_access;
IInterface* dereference() { return this->base()->pObject->GetInterface(); }
};
Run Code Online (Sandbox Code Playgroud)
您可以创建这种类型的内部Container
,并从其返回begin()
和end()
方法.
其次,您需要运行时多态MagicIterator
.这正是这样any_iterator
做的.的MagicIterator<IInterface*>
只是any_iterator<IInterface*, boost::forward_traversal_tag, IInterface*>
,并且cont_iter
可以只分配给它.
创建一个抽象IteratorImplementation
类:
template<typename T>
class IteratorImplementation
{
public:
virtual ~IteratorImplementation() = 0;
virtual T &operator*() = 0;
virtual const T &operator*() const = 0;
virtual Iterator<T> &operator++() = 0;
virtual Iterator<T> &operator--() = 0;
};
Run Code Online (Sandbox Code Playgroud)
以及一个Iterator
围绕它的类:
template<typename T>
class Iterator
{
public:
Iterator(IteratorImplementation<T> * = 0);
~Iterator();
T &operator*();
const T &operator*() const;
Iterator<T> &operator++();
Iterator<T> &operator--();
private:
IteratorImplementation<T> *i;
}
Iterator::Iterator(IteratorImplementation<T> *impl) :
i(impl)
{
}
Iterator::~Iterator()
{
delete i;
}
T &Iterator::operator*()
{
if(!impl)
{
// Throw exception if you please.
return;
}
return (*impl)();
}
// etc.
Run Code Online (Sandbox Code Playgroud)
(您可以在IteratorImplementation
“内部”创建一个类Iterator
以保持整洁。)
在您的类中Container
,返回一个Iterator
带有自定义子类的实例:IteratorImplementation
ctor
class ObjectContainer
{
public:
void insert(Object *o);
// ...
Iterator<Object *> begin();
Iterator<Object *> end();
private:
class CustomIteratorImplementation :
public IteratorImplementation<Object *>
{
public:
// Re-implement stuff here.
}
};
Iterator<Object *> ObjectContainer::begin()
{
CustomIteratorImplementation *impl = new CustomIteratorImplementation(); // Wish we had C++0x's "var" here. ;P
return Iterator<Object *>(impl);
}
Run Code Online (Sandbox Code Playgroud)
我现在找到了一个更适合我最初目的的解决方案。但我还是不喜欢它:)
该解决方案涉及在 IInterface* 上模板化 MagicIterator,并使用迭代器的 void*、所述迭代器的字节大小以及指向在所述 void* 上执行标准迭代函数(例如递增、递减、 MagicIterator 假定将给定迭代器 memcpy 到内部缓冲区中是安全的,并通过将其自己的缓冲区作为 void* 传递给提供的函数来实现其自己的成员,就像它是原始迭代器一样。
然后,容器必须实现静态迭代函数,将提供的 void* 强制转换为 std::list::iterator。Container::begin() 和 Container::end() 只是构造一个 std::list::iterator,将指向它的指针及其迭代函数表传递到 MagicIterator 中,然后返回 MagicIterator。
这有点令人恶心,并且打破了我关于“no memcpy()”的原始规则,并对相关迭代器的内部结构做出了假设。但它避免了堆分配,保持 Collection 的内部结构(包括 Item)私有,使 MagicIterator 完全独立于所讨论的集合和 IInterface*,并且理论上允许 MagicIterators 与任何集合一起工作(前提是它的迭代器可以安全地 memcopy()' d).