[英]C++ Iterator for std::set or std::vector
假設我有這個:
struct HoldStuff {
std::vector<StuffItem> items;
std::set<StuffItem, StuffItemComparator> sorted_items;
}
現在,在重構期間,我可能在items
包含東西,或者可能在sorted_items
其sorted_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_range
或any_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>::iterator
列std::vector<StuffItem>::iterator
( std::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.