1. ホーム
  2. c++

[解決済み] 複数のforループをきれいに書く方法

2023-01-04 20:53:51

質問

多次元の配列の場合、通常は for ループを書く必要があります。例えば

vector< vector< vector<int> > > A;

for (int k=0; k<A.size(); k++)
{
    for (int i=0; i<A[k].size(); i++)
    {
        for (int j=0; j<A[k][i].size(); j++)
        {
            do_something_on_A(A[k][i][j]);
        }
    }
}

double B[10][8][5];
for (int k=0; k<10; k++)
{
    for (int i=0; i<8; i++)
    {
        for (int j=0; j<5; j++)
        {
            do_something_on_B(B[k][i][j]);
        }
    }
}

このような for-for-for のループをよく見かけます。どのようにマクロを使って for-for-for ループを定義するマクロを使用して、この種のコードを毎回書き直す必要がないようにするにはどうしたらよいでしょうか?これを行うためのより良い方法はありますか?

どのように解決するのですか?

まず第一に、そのようなデータ構造を使わないことです。 もし 3次元の行列が必要なら、それを定義します。

class Matrix3D
{
    int x;
    int y;
    int z;
    std::vector<int> myData;
public:
    //  ...
    int& operator()( int i, int j, int k )
    {
        return myData[ ((i * y) + j) * z + k ];
    }
};

また、インデックスを作成する場合は [][][] を使う場合は operator[] で、これはプロキシを返します。

一旦これを実行すると、もしあなたが提示したように常に イテレータを公開します。 を公開します。

class Matrix3D
{
    //  as above...
    typedef std::vector<int>::iterator iterator;
    iterator begin() { return myData.begin(); }
    iterator end()   { return myData.end();   }
};

では、ただ書くだけです。

for ( Matrix3D::iterator iter = m.begin(); iter != m.end(); ++ iter ) {
    //  ...
}

(あるいは単に

for ( auto& elem: m ) {
}

C++11をお持ちの場合)

また、このような反復の間に3つのインデックスが必要な場合、それらを公開するイテレータを作成することができます。 それらを公開するイテレータを作成することが可能です。

class Matrix3D
{
    //  ...
    class iterator : private std::vector<int>::iterator
    {
        Matrix3D const* owner;
    public:
        iterator( Matrix3D const* owner,
                  std::vector<int>::iterator iter )
            : std::vector<int>::iterator( iter )
            , owner( owner )
        {
        }
        using std::vector<int>::iterator::operator++;
        //  and so on for all of the iterator operations...
        int i() const
        {
            ((*this) -  owner->myData.begin()) / (owner->y * owner->z);
        }
        //  ...
    };
};