[英]C++ Iterator for C Linked Lists: to use range-based for loops
我正在使用舊的C
代碼,新代碼是用C++
編寫的。 為了使用 C++ 標准庫,我在閱讀了 Bjarne Stroustrup 關於Adaptation的博文后,為舊版LinkedList
編寫了一個簡單的Iterator
,如下所示。
我的問題是:
我想為另一個struct
創建另一個Iterator
,比如struct TokenList
。 我不確定如何使用namespace
並且仍然能夠使用基於范圍的for
循環。 任何指針都會有所幫助。
Iterator
的適配器,即: begin
, end
, ++
, *
, !=
正確嗎? 目前,我對使用基於范圍的for
循環讀取LinkedList
的內容很感興趣。
#include <cstdio>
#include <numeric>
#include <algorithm>
struct LinkedList {
double v;
LinkedList *next;
};
struct Iterator {
LinkedList *current;
LinkedList &c;
};
Iterator begin(LinkedList *c) { return Iterator {c, *c}; }
Iterator end(LinkedList *c) { return Iterator {nullptr, *c}; }
Iterator &operator++(Iterator &p) { p.current = p.current->next; return p; }
LinkedList *operator*(Iterator p) { return p.current; }
bool operator!=(Iterator lhs, Iterator rhs) { return (lhs.current != rhs.current); }
int main()
{
LinkedList *node1 = new LinkedList;
LinkedList *node2 = new LinkedList;
LinkedList *node3 = new LinkedList;
node1->v = 1; node1->next = node2;
node2->v = 2; node2->next = node3;
node3->v = 3; node3->next = nullptr;
printf("// C style: iteration\n");
for (auto ptr = node1; ptr; ptr = ptr->next) {
printf("%e\n", ptr->v);
}
auto head = node1;
// make use of begin(), end(), ++, != and *
printf("// Modern C++ style: range based for-loop\n");
for (const auto& it : head) {
printf("%e\n", it->v);
}
std::for_each(begin(head), end(head), [](auto t) { delete t; });
return 0;
}
迭代器是偽指針類型。 這意味着他們自己是有規律的。
struct Iterator {
LinkedList *current;
LinkedList &c;
};
在這里你混合引用和指針。 這是一個嚴重的反模式,賦值是做什么的? 沒有明智的答案。
我會完全刪除c
成員。
接下來你需要廣播一個迭代器類型。 你的看起來像一個前向迭代器。 所有結束迭代器都可以相等。
Iterator begin(LinkedList *c) { return Iterator {c, *c}; }
Iterator end(LinkedList *c) { return Iterator {nullptr, *c}; }
這些看起來不錯。
請注意,名稱不必是Iterator
。 begin
/ end
必須在LinkedList
的命名空間中定義,但返回類型不必是。
Iterator &operator++(Iterator &p) { p.current = p.current->next; return p; }
我通常將其實現為成員 function,並實現前后遞增; post 是使用 pre 和 copy 實現的。
LinkedList *operator*(Iterator p) { return p.current; }
這是錯誤的。 它應該返回*p.current
作為double&
。
bool operator!=(Iterator lhs, Iterator rhs) { return (lhs.current != rhs.current); }
當然。 還將==
實現為!(lhs!=rhs)
。
查找前向迭代器概念和前向迭代器標簽。 包括std::iterator_traits
所需的類型。
對於其他要迭代的東西,給迭代器一個不同的名字。 這可以通過不同的命名空間。
如果不同的只是值的類型,你可以很容易地把它變成一個模板。 然后你只需要手動編寫begin
/ end
。
如果v
的名稱也發生變化,您可以在作為自定義點編寫的GetValue(List*)
function 上使用 ADL。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.