一度どハマりしたことがあるのでメモ。
std::accumulateは、vectorなどコンテナの要素を加算してくれる便利な関数だが、第三引数にちょっと罠がある。
まず特に問題ないサンプル。
1 2 3 4 5 6 7 8 9 10 |
#include <vector> #include <iostream> #include <numeric> int _tmain(int argc, _TCHAR* argv[]) { using namespace std; vector<int> v = { 1, 2, 3 }; cout << "sum : " << accumulate( v.begin(), v.end(), 0 ) << endl; } |
出力結果 : sum : 6
ところが以下の例だと値が丸められてしまう。
1 2 3 4 5 6 7 |
int _tmain(int argc, _TCHAR* argv[]) { using namespace std; vector<double> dbl_v = { 1.1, 2.2, 3.3 }; cout << "sum : " << accumulate( dbl_v.begin(), dbl_v.end(), 0 ) << endl; } |
出力結果 : sum : 6
この場合は、第三引数がdoubleでなくてはならない。
1 2 3 4 5 6 7 |
int _tmain(int argc, _TCHAR* argv[]) { using namespace std; vector<double> dbl_v = { 1.1, 2.2, 3.3 }; cout << "sum : " << accumulate( dbl_v.begin(), dbl_v.end(), 0.0 ) << endl; } |
出力結果 : sum : 6.6
テンプレートクラス内などで使う場合はstatic_castを使う。
例えばメンバをvectorで保持するクラスに合計値を出す関数を実装する例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#include <vector> #include <numeric> template <typename T> class Test { private: // Member: std::vector<T> vals_; public: // Constructor: explicit Test( const std::vector<T>& v ) : vals_(v) {} // Method: T Sum()const { return std::accumulate( vals_.begin(), vals_.end(), static_cast<T>( 0 ) ); } }; |
出力してみる。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#include <iostream> #include "test_class.h" int _tmain(int argc, _TCHAR* argv[]) { using namespace std; vector<int> int_v = { 1, 2, 3 }; Test<int> int_test( int_v ); vector<double> dbl_v = { 1.1, 2.2, 3.3 }; Test<double> dbl_test( dbl_v ); cout << "sum : " << int_test.Sum() << endl; cout << "sum : " << dbl_test.Sum() << endl; return 0; } |
出力結果:
sum : 6
sum : 6.6