让iterable
是 类型Iterable
。然后,为了使
for (Type x : iterable)
编译,必须有类型被调用Type
,IType
并且必须有函数
IType Iterable::begin()
IType Iterable::end()
IType
必须提供功能
Type operator*()
void operator++()
bool operator!=(IType)
整个结构实际上是复杂的语法糖,例如
for (IType it = iterable.begin(); it != iterable.end(); ++it) {
Type x = *it;
...
}
Type
可以使用任何兼容类型(例如const Type
or )来代替Type&
,这将具有预期的含义(常量性、引用代替复制等)。
由于整个扩展是在语法上发生的,您还可以稍微更改运算符的声明,例如让 *it 返回一个引用或让 !=const IType& rhs
根据需要采用 a。
请注意,如果不返回引用,则不能使用for (Type& x : iterable)
表单(但如果返回引用,您也可以使用复制版本)。*it
另请注意,它operator++()
定义了运算符的前缀版本++
- 但是它也将用作后缀运算符,除非您明确定义后缀++
。如果您只提供一个 postfix ++
,则 ranged-for 将不会编译,btw.can 可以声明为operator++(int)
(虚拟 int 参数)。
最小的工作示例:
#include <stdio.h>
typedef int Type;
struct IType {
Type* p;
IType(Type* p) : p(p) {}
bool operator!=(IType rhs) {return p != rhs.p;}
Type& operator*() {return *p;}
void operator++() {++p;}
};
const int SIZE = 10;
struct Iterable {
Type data[SIZE];
IType begin() {return IType(data); }
IType end() {return IType(data + SIZE);}
};
Iterable iterable;
int main() {
int i = 0;
for (Type& x : iterable) {
x = i++;
}
for (Type x : iterable) {
printf("%d", x);
}
}
输出
0123456789
您可以使用以下宏伪造 ranged-for-each(例如,对于较旧的 C++ 编译器):
#define ln(l, x) x##l // creates unique labels
#define l(x,y) ln(x,y)
#define for_each(T,x,iterable) for (bool _run = true;_run;_run = false) for (auto it = iterable.begin(); it != iterable.end(); ++it)\
if (1) {\
_run = true; goto l(__LINE__,body); l(__LINE__,cont): _run = true; continue; l(__LINE__,finish): break;\
} else\
while (1) \
if (1) {\
if (!_run) goto l(__LINE__,cont);/* we reach here if the block terminated normally/via continue */ \
goto l(__LINE__,finish);/* we reach here if the block terminated by break */\
} \
else\
l(__LINE__,body): for (T x = *it;_run;_run=false) /* block following the expanded macro */
int main() {
int i = 0;
for_each(Type&, x, iterable) {
i++;
if (i > 5) break;
x = i;
}
for_each(Type, x, iterable) {
printf("%d", x);
}
while (1);
}
(如果您的编译器甚至没有自动功能,请使用 declspec 或传递 IType)。
输出:
1234500000
正如您所看到的,continue
并且break
由于其复杂的结构而可以使用它。请参阅http://www.chiark.greenend.org.uk/~sgtatham/mp/了解更多 C-preprocessor hacking 以创建自定义控制结构。