我的代码中有一个块,其中for循环应该根据条件向前或向后运行。
if (forwards) {
for (unsigned x = 0; x < something.size(); x++ ) {
// Lots of code
}
} else {
for (unsigned x = something.size()-1 ; x >= 0 ; x-- ) {
// Lots of code
}
}
有没有一种很好的方法来设置它,所以我不会重复两次for循环中的所有代码?
有问题的'东西'是std :: vector&lt;&gt;,所以也许它可能带有迭代器? (我没有使用C ++ 11)
答案 0 :(得分:7)
将循环值与循环中使用的值分开:
for (unsigned x2 = 0; x2 < something.size(); x2++ ) {
const int x = forward ? x2 : (something.size()-1) - x2;
// Lots of code using x
}
答案 1 :(得分:6)
最简单的方法可能是将Lots of code
转换为带参数x
的函数,并用对该函数的调用替换这两个循环体:
void do_lots_of_stuff(unsigned x) {
// Lots of code
}
////////
if (forwards) {
for (unsigned x = 0; x < something.size(); x++ ) {
do_lots_of_stuff(x);
}
} else {
for (unsigned x = something.size()-1 ; x >= 0 ; x-- ) {
do_lots_of_stuff(x);
}
}
答案 2 :(得分:3)
或者你可以这样做:
for (unsigned x = (forward ? 0: something.size()); x != (forward ? something.size() :0); forward? x++: x-- ) {
// Lots of code
}
编译器很可能会优化它并仅评估forward
一次,因为它的值在我假设的for
循环中没有变化。
答案 3 :(得分:2)
template<typename Cont, typename Func>
Func directional_for_each(Cont c, bool forwards, Func f) {
return forwards ? for_each(begin(c), end(c), f) : for_each(rbegin(c), rend(c), f);
}
像这样使用:
vector<int> v;
// put stuff in v...
bool forwards = false;
directional_for_each(v, forwards, [](decltype(v[0]) x) {
// Lots of code using x
});
由于您没有使用C ++ 11,因此必须使用其他地方定义的函数替换包含“使用x的许多代码”的lambda。
答案 4 :(得分:0)
我碰巧碰到了这个问题,并且认为我可以提供一个解决方案,无需有条件地检查每个循环是否向前或向后。
// Could do 0xFFFFFFFFU if unsigned is 32bits.
const unsigned MAX_UINT = 0U - 1U;
// Will need this later.
const bool backwards = !forwards;
// temp is either going to be one or zero.
const unsigned temp = unsigned(forwards);
// By adding it to all ones, if temp is ones the mask is all zeros
// else if temp is zero we get all ones.
const unsigned mask = temp + MAX_UINT;
// Bit shift temp over such that it will push all of the ones after
// the first bit to all zeros if temp is one. This means we will
// either have a one or a negative one if temp is zero.
const int delta = int((temp << 1) + MAX_UINT);
const int size = something.size();
// The mask will be zero if forwards is true therein i will start out
// at zero else the mask will be all ones therein return (size - 1).
for(int i = int((size - 1) & mask);
// This may be a more complicated check, but there is only one conditional branch.
(forwards && (i < size)) || (backwards (0 <= i));
i += delta)
{
// Lots of code
}