iota:連番を振る
まずはとっても簡単なiota、2つのイテレータで示されたコンテナ内の各要素を連番で埋めてくれます。
int x[10]; iota(x, x+10, 0);
これでx[0]..x[9] が 0, 1, 2, …… 9 で埋まります。第3引数が最初の値ですから、iota(x, x+10, 4)なら4, 5, 6, ……で埋まりますね。
Visual C++ 2013のiotaは、こんなコードで実装されていました:
template<class ForwardIterator, class T> void iota(ForwardIterator first, ForwardIterator last, T val) { for( ; first != last; ++first, ++val ) { *first = val; } }
ということは、イテレータがさす要素の型をQとして、第3引数に与えるT valがQに暗黙変換され、インクリメント演算子++が定義されていれば、どんなものでも構わんはずです。そんなクラス:sequence(数列)を書いてみました。
#ifndef SEQUENCE_H_ #define SEQUENCE_H_ #include <functional> /* * 数列: sequence */ template<typename T> class sequence { private: T val_; std::function<T(T)> succ_; public: sequence(T val, const std::function<T(T)>& succ) : val_(val), succ_(succ) {} // Tへの暗黙変換 operator T() const { return val_; } // 現在の値を基に次の値を作る sequence& operator++() { val_ = succ_(val_); return *this; } sequence operator++(int) { sequence r(*this); ++(*this); return r; } }; #endif
sequenceのコンストラクタには、初期値と(++されたときに)現在の値を基に次の値を返す関数オブジェクトを与えます。
vector<int> data(10); // 等差数列: 2, 4, 6, 8, 10, …… iota(begin(data), end(data), sequence<int>(2,[](int x){return x+2;})); for ( auto item : data ) cout << item << ' '; cout << endl; // 等比数列: 1, 2, 4, 8, 16, …… iota(begin(data), end(data), sequence<int>(1,[](int x){return x*2;})); for ( auto item : data ) cout << item << ' '; cout << endl;