LoginSignup
3
2

More than 1 year has passed since last update.

【C++】1行で配列やvectorの和を取る決定版

Posted at

多くの言語は一行で和がとれるのに、なぜ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

3
2
0

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
3
2