簡體   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