iteratorを引数にするジェネリック関数 iterator_traits
例えば2つのイテレータを受け取って平均を返す関数を書こうとすると、イテレータが指し示す型の情報がないと作れませんね。
こんなときは iterator_traits というものを使って書くようです。
例えば平均値を求める関数を書いてみると、次のようになります。
戻り値の型を typename std::iterator_traits
また合計値を求めるのはaccumulate()関数で行ってますが、この引数として value_type(0)が必要です。この value_type は関数冒頭でtypedefしています。
これは組み込み型の配列にも使えます。便利ですね。
#include <iostream> #include <algorithm> #include <numeric> #include <stdexcept> #include <iterator> #include <vector> template<class In> typename std::iterator_traits<In>::value_type my_ave(In b, In e) { typedef std::iterator_traits<In>::value_type value_type; value_type sum = std::accumulate(b, e, value_type(0)); if (b != e) { return sum / (e - b); } else { throw std::invalid_argument("no data"); } } int main() { // vectorの要素(double)の平均値 std::vector<double> v; for (int i = 0; i < 10; i++ ) { v.push_back(i); } std::cout << my_ave(v.begin(), v.end()) << std::endl; // クリアすると、例外が発生 v.clear(); try { std::cout << my_ave(v.begin(), v.end()) << std::endl; } catch(std::logic_error e) { std::cout << e.what() << std::endl; } // doubleの配列にも使える const double va[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; std::cout << my_ave(va, va + sizeof(va)/sizeof(*va)) << std::endl; return 0; }