我有一个'foreach'宏我经常在C++中使用,适用于大多数STL容器:
#define foreach(var, container) \
for(typeof((container).begin()) var = (container).begin(); \
var != (container).end(); \
++var)
Run Code Online (Sandbox Code Playgroud)
(注意'typeof'是gcc扩展名.)它的使用方式如下:
std::vector< Blorgus > blorgi = ...;
foreach(blorgus, blorgi) {
blorgus->draw();
}
Run Code Online (Sandbox Code Playgroud)
我想做一些类似迭代地图值的东西.也许称之为"foreach_value".所以不要写作
foreach(pair, mymap) {
pair->second->foo();
}
Run Code Online (Sandbox Code Playgroud)
我会写的
foreach_value(v, mymap) {
v.foo();
}
Run Code Online (Sandbox Code Playgroud)
我不能想出一个会这样做的宏,因为它需要声明两个变量:迭代器和值变量(上面的'v').我不知道如何在for循环的初始化器中做到这一点,即使使用gcc扩展.我可以在foreach_value调用之前声明它,但是它会与同一范围内的foreach_value宏的其他实例冲突.如果我可以将当前行号后缀为迭代器变量名,它可以工作,但我不知道该怎么做.
您将寻找BOOST_FOREACH - 他们已经为您完成了所有工作!
如果你想要自己动手,可以在C++的任何地方声明一个块,这可以解决你的中间存储器itr-> second的范围问题......
// Valid C++ code (which does nothing useful)
{
int a = 21; // Which could be storage of your value type
}
// a out of scope here
{
int a = 32; // Does not conflict with a above
}
Run Code Online (Sandbox Code Playgroud)
您可以使用两个循环来完成此操作。第一个声明迭代器,其名称是容器变量的函数(如果您担心与您自己的代码发生冲突,您可以使它更难看)。第二个声明值变量。
#define ci(container) container ## iter
#define foreach_value(var, container) \
for (typeof((container).begin()) ci(container) = container.begin(); \
ci(container) != container.end(); ) \
for (typeof(ci(container)->second)* var = &ci(container)->second; \
ci(container) != container.end(); \
(++ci(container) != container.end()) ? \
(var = &ci(container)->second) : var)
Run Code Online (Sandbox Code Playgroud)
通过使用相同的循环终止条件,外循环只发生一次(如果幸运的话,会被优化掉)。此外,如果地图为空,则避免在迭代器上调用 ->second 。这与内循环增量中三元运算符的原因相同;最后,我们只将 var 留在最后一个值,因为它不会再次被引用。
您可以内联 ci(container),但我认为它使宏更具可读性。