コンテナ以外でのrange-based for loopの利用例

# 概要
c++11以降で使えるRange-based forループをコンテナ(vector やlist)以外で使う場合にどうしたらいいかという例です．３次元画像処理のプログラムを書いている時に多重ループになって面倒くさいと思ったので，調べてみました．

[cppreference.comのrange-based for loop](http://en.cppreference.com/w/cpp/language/range-for) に内部的な処理が書いてあったのを参考にしました．

範囲を表すクラス(Rangeとする）について，
- iterator Range::begin()メソッド
- iterator Range::end()メソッド
- Range:iterator クラス
- Range::iteratorクラスに対する ++オペレータ
- Range::iteratorクラスに対する *オペレータ
があればコンテナでないオブジェクトでもrange-based for loopが使えそうです．

# 例題
この例は，(-1, -1, -1) - (1, 1, 1)の範囲を走査し，座標値を出力します．Rangeクラスは，コンテナを保持していません．単純なfor ループだと３重ループになります．Iteratorを自分で定義しても１重ループになりますが，この方法のほうが記述量が減り，圧倒的にシンプルになると思います．

```cpp:range_based_for.cpp
#include <iostream>

class Point3i
{
public:
        int x;
        int y;
        int z;
public:
        Point3i ( const int x0 = 0, const int y0 = 0, const int z0 = 0 ) : x( x0 ), y( y0 ), z( z0 )
        {
                return;
        }

        Point3i ( const Point3i& p )
        {
                this->x = p.x;
                this->y = p.y;
                this->z = p.z;
                return;
        }

        Point3i operator = ( const Point3i& p )
        {
                this->x = p.x;
                this->y = p.y;
                this->z = p.z;
                return *this;
        }

        bool operator != ( const Point3i& that ) const
        {
                return this->x != that.x || this->y != that.y || this->z != that.z;
        }
};

std::ostream& operator << ( std::ostream& out, const  Point3i& p )
{
        out << p.x << " " << p.y << " " << p.z;
        return out;
}

class Range
{
public:

        class iterator
        {
        private:
                const Range& _range;
                Point3i _now;
        public:
                explicit iterator ( const Range& range, const bool isBegin ) : _range( range )
                {
                        this->_now  = range.getMin();
                        //end が指し示す位置は，(bmin.x, bmin.y, bmax.z+1)
                        if ( !isBegin ) this->_now.z = range.getMax().z + 1;
                }

                Point3i operator * ( void )
                {
                        return this->_now;
                }

                bool operator != ( const iterator& that )
                {
                        return this->_now != that._now;
                }

                iterator&
                operator++( void )
                {
                        this->step_forward();
                        return *this;
                }
        private :
                void step_forward( void )
                {
                        const Point3i bmin = this->_range.getMin();
                        const Point3i bmax = this->_range.getMax();

                        Point3i& pos = this->_now;
                        if ( bmax.z < pos.z ) return;

                        pos.x += 1;
                        if ( bmax.x < pos.x ) {
                                pos.x = bmin.x;
                                pos.y += 1;
                                if ( bmax.y < pos.y ) {
                                        pos.y = bmin.y;
                                        pos.z += 1;
                                }
                        }
                        return;
                }
        };
private:
        Point3i _bmin;
        Point3i _bmax;
public:
        Range ( const Point3i& bmin , const Point3i& bmax ) : _bmin ( bmin ) , _bmax( bmax )
        {
                return;
        }

        Point3i getMin( void ) const
        {
                return this->_bmin;
        }

        Point3i getMax( void ) const
        {
                return this->_bmax;
        }

        Range::iterator begin ( void )
        {
                return Range::iterator( *this, true );
        }

        Range::iterator end ( void )
        {
                return Range::iterator( *this, false );
        }
};

int main ( int argc, char** argv )
{
        Range range ( Point3i( -1, -1, -1 ), Point3i( 1, 1, 1 ) );

        for ( auto p : range ) { 
                std::cerr << p << std::endl;
        }
        /* for 文の場合こうなる 
        for ( Range::iterator p = range.begin() ; p != range.end() ; ++p ) {
                std::cerr << ( *p ) << std::endl;
        }
        */
        /* iteratorを使わないとこうなる 
        for ( int z = -1 ; z <= 1 ; ++z ) {
              for ( int y = -1 ; y <= 1 ; ++y ) {
                    for ( int x = -1 ; x <= 1 ; ++x ) {
                       std::cerr<<Point3i(x, y, z)<<std::endl;
                    }
              }
         }
        */

        return 0;
}
```

```cmake:CMakeLists.txt
CMAKE_MINIMUM_REQUIRED (VERSION 2.6)
PROJECT(range_based_for)
ADD_EXECUTABLE(range_based_for range_based_for.cpp )
ADD_DEFINITIONS(-g -O3 -Wall --std=c++11) #c++11なので必要
```

```bash:実行例
$ ./range_based_for
-1 -1 -1
0 -1 -1
1 -1 -1
-1 0 -1
0 0 -1
1 0 -1
-1 1 -1
0 1 -1
1 1 -1
-1 -1 0
0 -1 0
1 -1 0
-1 0 0
0 0 0
1 0 0
-1 1 0
0 1 0
1 1 0
-1 -1 1
0 -1 1
1 -1 1
-1 0 1
0 0 1
1 0 1
-1 1 1
0 1 1
1 1 1
$ 
```
修正
* 参照にしても意味がないので&とりました。( ```for ( auto p : range )``` ) (2021/01/21)