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;
