自定義類別支援 range-based for loop 寫法

本篇 ShengYu 介紹如何讓自定義類別支援 range-based for loop 的寫法。

range-based for loop 是 C++11 中增加的新特性,使用 range-based for loop 避免了存取越界,也提高了程式的可讀性以及寫程式的效率。range-based for loop 的寫法如下,先來複習一下,

1
2
3
4
vector<int> vec = {1, 2, 3};
for (auto& v : vec) {
cout << v << endl;
}

要讓自己寫的 class 支援 range-based for loop 關鍵在於實作 begin()end(),如下範例所示,如果自己寫的 class 沒有實作 begin()end() 的話會出現 error: invalid range expression of type 'MyList'; no viable 'begin' function available 的編譯錯誤訊息,以下範例以自定義的 MyList 與 std::list 為例,MyList 內部還是使用 std::list 當作主要的存取容器,這邊就要來寫 begin()end() 的實作來支援 range-based for loop 的寫法,

cpp-myclass-range-based-for-loop.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// g++ cpp-myclass-range-based-for-loop.cpp -o a.out -std=c++11
#include <iostream>
#include <list>
using namespace std;

class MyList {
public:
MyList() {}

void push_back(int n) { mList.push_back(n); }

list<int>::iterator begin() { return mList.begin(); }
list<int>::iterator end() { return mList.end(); }
list<int>::const_iterator begin() const { return mList.cbegin(); }
list<int>::const_iterator end() const { return mList.cend(); }
// or
//auto begin() { return mList.begin(); } // need C++14
//auto end() { return mList.end(); } // need C++14
//auto begin() const { return mList.begin(); } // need C++14
//auto end() const { return mList.end(); } // need C++14
private:
list<int> mList;
};

int main() {
list<int> list1;
list1.push_back(1);
list1.push_back(2);
list1.push_back(3);
for (auto& l : list1) {
cout << l << endl;
}

MyList list2;
list2.push_back(4);
list2.push_back(5);
list2.push_back(6);
for (auto& l : list2) {
cout << l << endl;
}

return 0;
}

輸出如下,這樣 MyList 跟原本的 list 容器一樣都能提供 支援 range-based for loop 的寫法了,

1
2
3
4
5
6
1
2
3
4
5
6

其他參考
c++ - How to allow range-for loop on my class? - Stack Overflow
https://stackoverflow.com/questions/18321092/how-to-allow-range-for-loop-on-my-class
[c++]自定义class的for each loop_I have a adream-CSDN博客
https://blog.csdn.net/adream307/article/details/86721033
AOSP 的 service_list class
https://github.com/aosp-mirror/platform_system_core/blob/34a0e57a257f0081c672c9be0e87230762e677ca/init/service_list.h
service_list 使用 range-based for loop 的範例在 service_utils.cpp 裡
https://github.com/aosp-mirror/platform_system_core/blob/34a0e57a257f0081c672c9be0e87230762e677ca/init/test_utils/service_utils.cpp