繁体   English   中英

如何返回通用迭代器(独立于特定容器)?

[英]How to return a generic iterator (independent of particular container)?

我想设计一个类Foo ,它存储不同类型的各种数据,并通过它们返回迭代器。 它应该是通用的,因此Foo的用户不知道数据是如何存储的( Foo可能使用std::setstd::vector或其他)。

我很想写一个这样的界面:

class Foo {
  class FooImpl;
  FooImpl* impl_;
public:
  const Iterator<std::string>& GetStrings() const;
  const Iterator<int>& GetInts() const;
};

Iterator就像这样(就像.NET中的迭代器一样):

template<class T>
class Iterator {
public:
  const T& Value() const = 0;
  bool Done() const = 0;
  void Next() = 0;
};

但是我知道这种迭代器在C ++中不是标准的,并且最好像STL一样使用迭代器,所以你可以在它们上使用STL算法。

我怎样才能做到这一点? (我有机会需要iterator_traits吗?)

您是否理解为什么STL选择将迭代器实现细节放在头文件中? JIT框架能够跨编译单元内联,但C ++只能在编译单元中内联。 内联时推进序列的速度要快得多,函数调用的成本实际上主要是遍历数据结构。

如果您真的想隐藏实现细节,请继续。 你可以创建一个STL兼容的迭代器来实现operator ++和operator!=和operator->就受保护的虚函数而言,你提到的Next,Done和Value都是不错的名字。 只希望以较低的性能为封装付费。

使用typedef返回boost::iterator_range 例如(不要介意名字),

class Container
{
     typedef std::vector<int> Collection; 

     public:
     typedef boost::iterator_range<Collection::iterator> CollectionRange;
     typedef Collection::iterator CollectionIterator;
     Range range() const {
          return make_iterator_range(collection_.begin(), collection_.end());
     }

     private:
     Collection collection_;          
};

用户代码将是

Container c;
// ...
FOREACH(int i, c.range()) { //... }
Container::Range r = c.range();
for(Container::iterator j = r.begin(); j!= r.end(); j++) { // ... }

这不是通用的,但同样的想法可以用于模板。

带有迭代器的c ++类必须至少提供两个函数,如果它们必须使用std库

iterator begin() //returns an iterator at starting pos
iterator end() //returns an iterator one past end or just invald

迭代器必须重载增量运算符,等于和*

iterator operator++()
iterator operator==()//make sure that an invalid iterator equals end()
T& operator*()

您可以使用迭代器类来包装内部存储的迭代器,以确保用户仅限于这些方法。

template <typename T> iter
{
   iter(T::iterator& intern)
   T::value_type& operator*(){return *intern}
  iter operator++(){return iter(++intern);}
  bool operator==(iter const& other)const{return intern == other.intern;}
}

其中T是你的容器的类型。(这个类是不完整的,我可能混淆了一些东西)

它几乎看起来像你正在尝试创建与容器无关的代码,这通常不是一个好主意,除非你正在编写一个只能用迭代器操作的算法。 (参见Scott Myers Effective STL第2项:注意与容器无关的代码的错觉)

问题是大多数标准容器不提供重叠功能。 如果您正在为特定容器编写代码,请假设您正在为该容器编写代码。 不要试图使其与容器无关。

为了满足头文件中未提及特定容器(vector,set,...)以及用户将能够遍历所有字符串的要求,使用访问者模式 当然,缺点是用户将无法在字符串上使用STL算法。

// foo.h
class StringVisitor {
public:
  void accept(const std::string& str) {
    std::cout << str << std::endl;
  }
};
class Foo {
  class Impl;
  Impl* impl_;
public:
  Foo();
  ~Foo();
  void VisitStrings(StringVisitor v) const;
};

// foo.cc
class Foo::Impl {
  typedef std::vector<std::string> StringContainer;
  StringContainer str_;
public:
  Impl() {
    str_.push_back("a");
    str_.push_back("b");
  }
  void VisitStrings(StringVisitor v) const {
    for(StringContainer::const_iterator it = str_.begin();
    it != str_.end(); ++it){
      v.accept(*it);
    }
  }  
};

Foo::Foo() : impl_(new Impl()) {}
Foo::~Foo() {delete impl_;}
void Foo::VisitStrings(StringVisitor v) const {
  impl_->VisitStrings(v);
}

// main.cc
int main() {
  Foo foo;
  foo.VisitStrings(StringVisitor());
  return 0;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM