多くの言語は一行で和がとれるのに、なぜC++はfor文を回さないといけないのか、、
そんな疑問が記事になりました。
この記事では、配列やvectorの和を1行で取る方法を紹介します。
また汎用性と安全性に配慮しているので、どんな型でも安心してご利用いただけます。
脱・安直なaccumulate()!
C++17以上の場合
reduce()を使いましょう。
#include <array>
#include <iostream>
#include <numeric>
#include <vector>
#include <set>
int main() {
float v[] = {1.1, 1.2, 1.4};
// std::vector<float> v = {1.1f, 1.2f, 1.4f};
// std::set<float> v = {1.1f, 1.2f, 1.4f};
// std::array v = {1.1f, 1.2f, 1.4f};
float sum = std::reduce(std::begin(v), std::end(v)); // どの型でも無事3.7が出力される
std::cout << sum << std::endl;
}
n要素までの和を取りたければ、std::next(itr, n)
を使います。静的配列などで使えそうですね。
float sum = std::reduce(std::begin(v), std::next(std::begin(v), 2)); // 2.3
C++11以上の場合
reduce()の代わりに、accumulate()を使いましょう。
#include <array>
#include <iostream>
#include <numeric>
#include <vector>
#include <set>
int main() {
float v[] = {1.1, 1.2, 1.4};
// std::vector<float> v = {1.1f, 1.2f, 1.4f};
// std::set<float> v = {1.1f, 1.2f, 1.4f};
// std::array v = {1.1f, 1.2f, 1.4f};
float sum = std::accumulate(
std::begin(v), std::end(v),
std::remove_reference<decltype(*std::begin(v))>::type{});
std::cout << sum << std::endl;
}
C++17の例と同様にn要素までの和が計算できます。
汎用性と安全性
上記の方法は次の特徴を持ちます。
- 配列もvectorもarrayもsetも、みんな同じように和を計算できる(汎用性)
- 第三引数の罠にハマらない(安全性)
実はreduceもaccumulateも第三引数に愚直に0
を入れると、暗黙的なダウンキャストが発生する可能性があります。注意しましょう。
✕悪い例
std::vector<float> v = {1.1, 1.2, 1.4};
float sum = std::accumulate(v.begin(), v.end(), 0); // 3.7を期待したはずが、3に!
詳しくは下の記事をご参照ください。
おわりに
C++11未満の方は頑張ってfor文を書いてください。
thanks: @yumetodo