C++11 如何迭代计数器的整个范围/wo溢出?

C++11 如何迭代计数器的整个范围/wo溢出?,c++11,C++11,如何为某些类型的每个成员执行循环体?我知道我可以在循环之后为maxval重复循环体,但这会复制不好的代码。我也可以用身体做一个函数,但我觉得这也不对,因为函数应该是小而简单的,循环的身体是巨大的 const auto minval = std::numeric_limits<T>::min(); const auto maxval = std::numeric_limits<T>::max(); for (auto i = minval; i < maxval; +

如何为某些类型的每个成员执行循环体?我知道我可以在循环之后为
maxval
重复循环体,但这会复制不好的代码。我也可以用身体做一个函数,但我觉得这也不对,因为函数应该是小而简单的,循环的身体是巨大的

const auto minval = std::numeric_limits<T>::min();
const auto maxval = std::numeric_limits<T>::max();
for (auto i = minval; i < maxval; ++i) {
    // huge body of the loop
}
const auto minval=std::numeric_limits::min();
const auto maxval=std::numeric_limits::max();
用于(自动i=minval;i
您必须保持一点附加状态,以指示是否已看到最后一个值。下面是一个简单的示例,可以将其转换为更惯用的迭代器样式,而无需做太多工作:

#include <iostream>
#include <limits>

using namespace std;

template <typename T>
class allvalues
{
public:

    allvalues() = default;

    T next()
    {
        if (done) throw std::runtime_error("Attempt to go beyond end of range");
        T v = val;
        done = v == std::numeric_limits<T>::max();
        if (!done) ++val;
        return v;
    }

    bool isDone() { return done; }

private:

    T val = std::numeric_limits<T>::min();
    bool done = false;
};

int main() {

    allvalues<char> range;
    while (!range.isDone())
    {
        std::cout << "Value = " << (int)range.next() << std::endl;
    }

    allvalues<unsigned char> urange;
    while (!urange.isDone())
    {
        std::cout << "Value = " << (unsigned int)urange.next() << std::endl;
    }
    std::cout << "That's it!" << std::endl;
}
#包括
#包括
使用名称空间std;
模板
类所有值
{
公众:
allvalues()=默认值;
T next()
{
如果(完成)抛出std::runtime_错误(“尝试超出范围结束”);
tV=val;
done=v==std::numeric_limits::max();
如果(!done)+val;
返回v;
}
bool isDone(){return done;}
私人:
T val=std::numeric_limits::min();
bool done=false;
};
int main(){
所有数值范围;
而(!range.isDone())
{

std::cout处理完最后一项后,只需停止即可:

auto i = minval;
while(1) {
    // do all the work for `i`


    if (i == maxval) break;
    ++i;
}
还可以将增量移动到循环的顶部,前提是在第一次传递时跳过该增量:

i = minval;
switch (1) {
case 0:
    do {
        ++i;
case 1:
        // processing for `i`
    } while (i != maxval);
}
后一个版本更直接地转换为高效的机器代码,因为每个循环迭代只有一个条件分支,并且有一个无条件分支,而在第一个版本中,有一个条件分支加上一个无条件分支,两者都重复每个迭代


这两个版本都没有增加最终值,这可能是未定义的行为。

不确定如何“但在我看来也是错误的,因为函数应该是小而简单的,循环体是巨大的”是一个参数,因为所有这些代码都需要以这样或那样的方式在函数中。无论如何,您也可以将其放入lambda中。正如我曾经学习过的那样,像使用
案例1:
那样跳入循环可能会适得其反。编译器是为了优化常见代码而构建的,因此,这样做很容易混淆编译器,从而导致没有编译器优化。因此,第二个代码实际运行速度可能比第一个代码慢得多。事实只在于度量,不同的编译器可能会有所不同。最好避免这种过早的优化,在没有证明它是有效的情况下,对代码抛出这样一个可怕的构造还为时过早t、 @cmaster:这可能令人惊讶,但这种情况并不罕见。这是对达夫设备的简化,它经常出现在循环展开过程中(自动和手动)。因此我希望优化器能够很好地处理它(尽管它可能会自动将第一个简单的源代码转换为第二个源代码).我知道达夫的设备,我也知道类似的东西曾经扼杀了我所有的编译器优化。在汇编程序中,它会像一个符咒一样工作,但在C语言中它是不可能实现的。我得出结论,使用达夫的设备和类似的技巧只是作为最后的手段,并且只有在严格的测量控制下。