LoginSignup
1
1

More than 5 years have passed since last update.

イテレータから示すものの型を取り出す

Last updated at Posted at 2015-06-08

状況説明

std::accumulateを使ってコンテナ内の数値の平均を求める関数を書いた。
(正確に言えばfirstからendまでの平均)

template<typename InputIt>
double mean(InputIt first, InputIt last,size_t size){
    return std::accumulate(first,last,0.0) / size;
}

平均なのだからdoubleで帰ってくれば良いという考え。

本題

intのコンテナからもdoubleの結果を返すようなことになるのは腑に落ちない。
引数のイテレータから型を取り出すように変更。
ついでに要素数もイテレータの距離で計算するようにした。

2015/06/09 追記:イテレータ間の距離を(last-first)で求めるには、ランダムアクセスイテレータが必要らしい。std:distance(first,last)なら他のイテレータでも問題ないそうなのでそっちに変更。

template<typename It>
using v_type = typename std::iterator_traits<It>::value_type;

template<typename InputIt>
v_type<InputIt> mean(InputIt first, InputIt last){
    return std::accumulate(first,last,v_type<InputIt>(0)) / std::distance(first,last);
    //return std::accumulate(first,last,v_type<InputIt>(0)) / (last-first);
}

型名がiterator_traitsのせいで長いので、エイリアステンプレートで別名をつけた。

疑問

上のやつの方が「イテレータ使ってる感」は強いが、このシチュエーションなら次のコードでよいのではないだろうか? 気持ち以上の差はあるのだろうか?

2015/06/09 追記:答えを教えていただいた。この書き方だとメモリ領域が不連続なコンテナ(std::listなど)には使えないそうだ。
std::vectorなどに使う分にはこれでよいようだが。

2015/06/09 追記 : なにか考え違いをしていたようだ。この形はC配列かstd::arrayとかが対象でないと手元の環境(clang 3.6.1)ではコンパイルが通らない。イテレータは一般にポインタに変換することはできないようだ。

template<typename T>
T mean(T* first, T* last){
    return std::accumulate(first,last,T(0)) / (last-first);
}

iterator_traits

今回のシチュエーションでは使わないが、iterator_traitsはイテレータが示すものの型(value_type)以外の情報も含んでいる。
たとえば引き算の結果の型(difference_type)とか、イテレータ自身の種類(iterator_category)とか。

1
1
4

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1