C++11で導入されたrange-based for statement、範囲for文ですが、この文に適用できるオブジェクトは配列や標準ライブラリのコンテナに限りません。
規格から大雑把に抽出すると、以下の条件を満たしていれば範囲for文に適用できます。
- 配列。配列の場合、範囲は与えられた配列の先頭から配列の要素数文を足したところまで
- 与えられたオブジェクトがbegin及びendメソッドを持っている
- begin及びendメソッドを適用できる(ADLで解決されるのでstd::begin/std::endに限らない)
なお、range-based for statementで適用されるbegin()及びend()の返すオブジェクトはoperator *()を持っていなければなりません。また、operator ++()も適用できねばなりません。
というわけで、boost::counting_iterator的なものを作ってみました。
#include <iostream>
// beginとendで返すオブジェクトの型
struct Numeric {
int i_;
Numeric(int t) : i_(t) {}
const int& operator *() const { return i_; }
const Numeric& operator ++() { ++i_; return *this; }
bool operator !=(const Numeric& r) const { return (i_ != r.i_); }
};
// グローバルなbegin()とend()を適用するクラス
struct NumericRangeA {
const Numeric begin_;
const Numeric end_;
NumericRangeA(const int& b, const int& e) : begin_(b), end_(e) {}
};
const Numeric& begin(const NumericRangeA& t) { return t.begin_; }
const Numeric& end(const NumericRangeA& t) { return t.end_; }
// begin()とend()メソッドを持つクラス
struct NumericRangeB {
const Numeric begin_;
const Numeric end_;
NumericRangeB(const int& b, const int& e) : begin_(b), end_(e) {}
const Numeric& begin() const { return begin_; }
const Numeric& end() const { return end_; }
};
int main()
{
using namespace std;
for(auto v : NumericRangeA(0, 10)) cout << v << " ";
cout << endl;
for(auto v : NumericRangeB(0, 10)) cout << v << " ";
cout << endl;
}
出力結果
0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
range-based for statementも、使い方次第で面白いことができるかもしれませんね。
それはそうと、C++erって細かい…おかげでこんなエントリ上げられたけどw