簡體   English   中英

用於std :: set或std :: vector的C ++迭代器

[英]C++ Iterator for std::set or std::vector

假設我有這個:

struct HoldStuff {
  std::vector<StuffItem> items;
  std::set<StuffItem, StuffItemComparator> sorted_items;
}

現在,在重構期間,我可能在items包含東西,或者可能在sorted_itemssorted_items ,但是無論我想對每個項目做同樣的事情。 我想做這樣的事情:

HoldStuff holder;  // assume it was filled earlier
auto iter = holder.items.empty() ? holder.sorted_items.begin() :
                                   holder.items.begin();
auto iter_end = holder.items.empty() ? holder.sorted_items.end() :
                                       holder.items.end();
for (; iter != iter_end; ++iter) {
    auto& item = *iter;
    // Do stuff
}

當我去編譯它時,我會抱怨關於不兼容的操作數類型的錯誤。 當然可以,不是嗎?

您有兩種選擇:

  • 使用類型擦除在迭代器( any_rangeany_iterator )上獲取運行時多態性
  • do_stuff委托給采用任何迭代器的函數模板

這是帶有代碼的插圖:

#include <vector>
#include <set>
#include <iostream>

#include <boost/range/any_range.hpp>

template<typename Iterator>
void do_stuff(Iterator begin, Iterator end) {}

int main()
{
  std::vector<int> items;
  std::set<int> sorted_items;
  // first option
  typedef boost::any_range<int, boost::forward_traversal_tag, int&, std::ptrdiff_t> my_any_range;
  my_any_range r;
  if(items.empty())
    r = my_any_range(sorted_items);
  else
    r = my_any_range(items);
  for (auto& x : r) {
    std::cout << x << " ";
  }

  // second option
  // this could also be a lambda and std::for_each
  if(items.empty())
    do_stuff(sorted_items.begin(), sorted_items.end());
  else
    do_stuff(items.begin(), items.end());
  return 0;
}

錯誤是正確的: auto關鍵字在編譯期間有效。 以一種簡單的方式,它只是推導分配的類型並使用這種類型。 但是決定是向量的迭代器還是集合的迭代器是在運行時決定的。 因此無法推論類型。 正如SergeyA所說,我在這里錯了,編譯器在?:運算符上失敗,然后自動。 但是原因仍然是相同的-它不知道要使用哪種類型的結果。

您可能應該使用一些更通用的迭代器類型+多態性,或者可以將此函數參數化為type,其中T是迭代器類型。 我更喜歡這樣:

template<class T> do_stuff(T &c) {  for (auto &el : c) { /*Whatever*/ } }

...

if (!items.empty()) {
    do_stuff(items);
} else if (!sorted_items.empty()) {
    do_stuff(sorted_items);
}     

PS:這是一個概念,我沒有測試代碼。

三元運算符的兩端都必須具有相同的類型。 在您的情況下,它們是不同的-std :: vector <> :: iterator和std :: set <>迭代器。 合適的解決方案似乎是某種迭代器包裝器,它會根據初始條件返回一個或另一個。

auto表示編譯器將在編譯時推斷出后續類型。

在這種情況下,三元條件運算符的返回類型是問號std::set<StuffItem, StuffItemComparator>::iterator因此它是std::set<StuffItem, StuffItemComparator>::iterator ,並且編譯器將嘗試std::vector<StuffItem>::iteratorstd::vector<StuffItem>::iteratorstd::vector<StuffItem>::iterator )轉換為此不兼容的類型,從而導致編譯器錯誤。

您可以做的是使商品處理代碼通用,如下所示:

auto doStuff = [] (StuffItem& item) {
  // do stuff with item...
};
if( holder.items.size() )
  for_each( holder.items.begin(), holder.items.end(), doStuff );
else if( holder.sorted_items.size() )
  for_each( holder.sorted_items.begin(), holder.sorted_items.end(), doStuff );

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM