5

(对于具体的编译器/平台上下文,请在 x86_64 上使用 GCC 4.7 和 Ubuntu 12.04)

给定一些函数 f:

void f(int x, int y);

int nx = ...;
int ny = ...;

迭代从 (0,0) 到 (nx,ny) 的每个值 (x,y) 的一种方法是:

for (int x = 0; x < nx; x++)
    for (int y = 0; y < ny; y++)
        f(x,y);

让它编译为一些生成的代码 Q1。

我们将编写一个函数 g 使得:

for (auto it : g(Z))
    f(it.x, it.y);

编译为代码 Q2。

是否可以编写 g 使得 Q2 与 Q1 一样有效?如果是,如何?如果不是,我们能得到的最接近的是什么?

如果有帮助,您可以将 auto 更改为 auto& 或 auto&&。

如果有帮助,您也可以将 it.x 更改为 it.x(),并将 it.y 更改为 it.y()。

(回想一下,基于范围的 for 的扩展只是您选择的类似迭代器的类型:C++11:基于范围的 for 语句:“range-init”生命周期?

4

2 回答 2

3

是否可以编写 g 使得 Q2 与 Q1 一样有效?如果是,如何?如果不是,我们能得到的最接近的是什么?

for当然可以,您只需要定义以与循环相同的方式递增的迭代器。从我的头顶:

class matrix_iterator
{
public:
    ...

    matrix_iterator& operator++()
    {
        if( ++y >= ny )
        {
            ++x;
            y = 0;
        }

        return *this;
    }

private:
    int nx, ny;
    int x, y;
};
于 2012-05-31T02:38:37.063 回答
2

此代码具有您想要的功能。我还没有验证它,但我怀疑它会产生与原始循环几乎相同的机器代码(在优化编译中)。

struct iter {
    int x, y, ny;
    iter(int x, int y, int ny) : x(x), y(y), ny(ny) {}
    iter &operator++ () {
        if (++y >= ny)
        {
            y = 0;
            ++x;
        }
        return *this;
    }
    bool operator != (iter const &rhs) const {
        return y != rhs.y || x != rhs.x;
    }
};

struct container {
    iter endit;
    container(int nx, int ny) : endit(nx, ny, ny) {}
    iter begin() const { return iter(0,0,endit.ny); }
    iter const &end() const { return endit; }
};

container g(Z const &z) { return container(z.nx, z.ny); }

for ( auto it : g(Z) )
    f(it.x, it.y);
于 2012-05-31T02:48:11.403 回答