【问题标题】:Using Iterators to hide internal container and achieve generic operation over a base container使用迭代器隐藏内部容器并在基础容器上实现通用操作
【发布时间】:2011-01-12 14:23:20
【问题描述】:

我基本上想要一个基础容器类,它可以返回一个通用迭代器,可以用来遍历容器类的实例,而不需要指定迭代器模板。我认为我无法通过类模板实现基本容器,这将需要基于事先不知道的模板类的遍历算法。可以使用其中的任何(自定义或标准)容器类型/实现来继承和实现基本容器。这里有一些代码示例可以清楚地说明:

struct MyObject {
  int myInt;
}

// an abstract container
class BaseContainer {
public:
  virtual void insertMyObject(MyObject& obj) = 0;
  virtual iterator getFirst(); // the iterator type is for demonstration purposes only
  virtual iterator getLast();  // the iterator type is for demonstration purposes only
}

// Sample container class that uses a std::vector instance to manage objects
class BaseContainer_Vector : public BaseContainer {
public:
  void insertMyObject(MyObject& obj); // e.g. just pushes back to the vector
  iterator getFirst(); // needs to override the iterator?
  iterator getLast();  // needs to override the iterator?
private:
  std::vector<MyObject> objectContainer;
}

然后我将拥有一个容器对象列表,并且我想遍历这些容器和存储的对象。

std::vector<MyContainer*> containers;
for(int i=0 ; i<containers.size() ; i++){
  iterator i    = containers[i]->getFirst();
  iterator iend = containers[i]->getLast();
  for(; i != iend ; i++) {
    std::cout << (*i).myInt << std::endl;
  }
}

我还希望支持 boost foreach 宏语句。只要 range_begin 和 range_end 函数正确,它就支持扩展。但是,boost doc 中的示例使用 std::string::iterator 作为返回类型,而我需要的是一个通用的迭代器类,我还不知道如何做到这一点。

std::vector<MyContainer*> containers;
for(int i=0 ; i<containers.size() ; i++){
  BOOST_FOREACH(MyObject obj, *(containers[i])) {
    std::cout << obj.myInt << std::endl;
  }
}

我想我可以定义自己的迭代器类,然后每个扩展 BaseContainer 的类都应该定义自己的迭代器来扩展该基本迭代器。然而,我更喜欢使用标准迭代器(stl 或 boost)来支持这种结构,而不是编写自己的迭代器。我想这种方法会奏效,但我对 cme​​ts 的效率持开放态度。

有没有可行的方法可以优雅地解决这个问题?还是我错过了一个可以毫无痛苦地解决这个问题的简单点?

可以在here 找到类似的问题,但建议的解决方案对于我的需求来说似乎有点复杂,而且据我所知,要求有所不同。

【问题讨论】:

  • 您正在处理的实际用例是什么?你真的需要两个动态选择的容器版本还是可以推送到编译时?
  • 我不确定它是否能很好地与 STL 和 boost 一起工作。那些通常假设迭代器是简单的值类型;如果要使用多态设计,值类型将不可用。
  • 我正在开发的库需要让用户定义自己的容器并将它们注册到系统中。系统遍历所有注册的容器并处理它们,我已经展示了一个使用 boost 的代码示例。系统还负责将 MyObject 类型自动插入到此容器中。我希望用户能够扩展这个容器类,以便他们可以在他们用来管理这些插入对象的任何结构上应用他们想要的任何顺序。

标签: c++ iterator


【解决方案1】:

这会很复杂。

如前所述,首先您需要迭代器具有值语义,因为它们通常会被复制,否则会导致对象切片。

class BaseContainer
{
protected:
  class BaseIteratorImpl; // Abstract class, for the interface

public:
  class iterator
  {
  public:
    iterator(const BaseIteratorImpl& impl);
  private:
    BaseIteratorImpl* m_impl;
  };

  iterator begin();
  iterator end();
}; // BaseContainer

然后,BaseIterator 将所有方法转发到 m_impl

通过这种方式,您可以使用多态核心实现值语义语法。

显然,您必须处理深拷贝语义和适当的破坏。

一些注意事项:

  • 同时发布 iteratorconst_iterator
  • 将您的方法命名为 emptysizebeginend 等...以与 STL 算法兼容

您可以查看SGI Iterators 以获取有关您的运营商应支持的概念和操作以实现最大兼容性的帮助。

【讨论】:

  • 感谢您的回复,我现在将尝试根据您的方法实现自定义迭代器。用户最终需要为内部使用的容器定义自定义增量、开始、结束操作。我会尽快报告结果:)
  • 我继承了您从 std::iterator<:forward_iterator_tag> 提出的公共迭代器类,因此也可以使其与 BOOST_FOREACH 一起使用 :) 感谢您指出正确的方向,它可以按照我的意愿工作,代码开销最小:)
  • 为有有趣问题的人提供帮助总是很高兴......或者至少是我感兴趣的问题:)
猜你喜欢
  • 1970-01-01
  • 2015-12-10
  • 2022-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多