在C++11中,可以這樣用已經不是什麼新鮮事了。
1 | vector<int> vec; |
如果要在自己的container支援這特性的話,需滿足以下條件。
- Container必須擁有
begin
、end
函數,這兩個函數必須回傳一個 Iterator 。 - Iterator必須擁有
*
、++ (prefix版)
、!=
這三個operator function。
以下範例是從C++11 range-based for loops修改而來,加上自己的實驗。在gcc跟clang都能正常運作,不過到了VC12 Debug Mode就編譯失敗了。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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105#include <iostream>
#include <algorithm>
using namespace std;
class IntVector;
class ConstIter
{
public:
ConstIter(const IntVector* p_vec, int pos)
: _pos(pos)
, _p_vec(p_vec)
{ }
bool operator!= (const ConstIter& other) const
{
return _pos != other._pos;
}
int operator* () const;
const ConstIter& operator++ ()
{
++_pos;
return *this;
}
private:
int _pos;
const IntVector *_p_vec;
};
class Iter
{
public:
Iter(IntVector* p_vec, int pos) : _pos(pos) , _p_vec(p_vec) { }
bool operator!= (const Iter& other) const
{
return _pos != other._pos;
}
int& operator* ();
Iter& operator++ ()
{
++_pos;
return *this;
}
private:
int _pos;
IntVector *_p_vec;
};
class IntVector
{
public:
int get(int col) const { return _data[col]; }
int& get(int col) { return _data[col]; }
IntVector() {}
Iter begin()
{
return Iter(this, 0);
}
Iter end()
{
return Iter(this, 100);
}
ConstIter begin() const
{
return ConstIter(this, 0);
}
ConstIter end() const
{
return ConstIter(this, 100);
}
void set(int index, int val)
{
_data[index] = val;
}
private:
int _data[100];
};
int
ConstIter::operator* () const
{
return _p_vec->get(_pos);
}
int&
Iter::operator* ()
{
return _p_vec->get(_pos);
}
int main()
{
IntVector v;
for (int i = 0; i < 100; i++)
v.set(i, i);
transform(v.begin(), v.end(), v.begin(), [](int v) { return v * 2; });
for (int& i : v) { i *= 2; }
for (const int& i : v) { cout << i << endl; }
}
這是由於Checked Iterator這巷特性。
最快的解決方案是在前面加上1
2
3
4
5
6#ifndef _ITERATOR_DEBUG_LEVEL
#define _ITERATOR_DEBUG_LEVEL 0
#else
#undef _ITERATOR_DEBUG_LEVEL
#define _ITERATOR_DEBUG_LEVEL 0
#endif