επιστημη [著] 2015/07/09 14:00
このエントリーをはてなブックマークに追加

サンプルファイル 120.79 KB
1 2 3 4 →

 「複数のプロジェクトを横断した設計~実装の後方支援」という役柄の僕は、さまざまなツールやライブラリ、サンプルコードを提供することが求められます。そのため空いた時間を見つけてはいろんなライブラリの味見をし、自分の持ち駒として溜め込むことにしています。今回は標準C++ライブラリの一つ、演算アルゴリズムを集めた<numeric>のご紹介です。

iota:連番を振る

 まずはとっても簡単なiota、2つのイテレータで示されたコンテナ内の各要素を連番で埋めてくれます。

list-1
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は、こんなコードで実装されていました:

list-2
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(数列)を書いてみました。

list-3 sequence.h
#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のコンストラクタには、初期値と(++されたときに)現在の値を基に次の値を返す関数オブジェクトを与えます。

list-4
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;

こちらの関連記事もおすすめです

プロフィール
επιστημη エピステーメー

C++に首まで浸かったプログラマ。

Microsoft MVP, Visual C++ (2004.01~) だったり
わんくま同盟でたまにセッションスピーカやったり
中国茶淹れてにわか茶人を気取ってたり、
あと Facebook とか。

著書:
- STL標準講座 (監修)
- C++テンプレートテクニック (共著)
- C++の設計と進化 (監修)
- ストラウストラップのプログラミング入門 (監修)
...など。


記事へのコメント・トラックバック機能は2011年6月に廃止させていただきました。記事に対する反響はTwitterやFacebook、ソーシャルブックマークサービスのコメントなどでぜひお寄せください。