0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ranges::toを使って関数型っぽくコンテナからコンテナを作る

Last updated at Posted at 2024-08-23

コンテナからコンテナを作る例として, 下記のような (フィボナッチ数列をメモ化を使って求める) コードがあるとする.
このコードでは vector<optional> を元にして, optional をはがした vector を作っている.

C++23以前
using std::vector;
using std::optional;

vector<int> fibo_wrapper(const int N) {
  // メモ化のための vector (メモ済かどうかを optional で表す)
  vector<optional<int>> memo(N + 1);
  // フィボナッチ数列をメモ化を使って求める (※中身は割愛)
  fibo(N, memo);

  // この関数の結果を格納する vector
  vector<int> results;
  results.reserve(N + 1);

  // optional をはがした結果を詰めていく
  for (const auto& o : memo) {
    results.push_back(o.value());
  }

  return results;
}

ここで, ranges::to (C++23) と views::transform (C++20) をつないだパイプラインを使うと, 下記のようにコンテナからコンテナを作れる.
一時変数 (results) や for 文がなくなり, 関数型っぽく書ける.

C++23以後: 関数型っぽく
#include <ranges>
using std::vector;
using std::optional;
using std::views::transform;
using std::ranges::to;

vector<int> fibo_wrapper(const int N) {
  // メモ化のための vector (メモ済かどうかを optional で表す)
  vector<optional<int>> memo(N + 1);
  // フィボナッチ数列をメモ化を使って求める (※中身は割愛)
  fibo(N, memo);

  // optional をはがして返す (パイプライン)
  return memo | transform([](const auto o) { return o.value(); })
              | to<vector>();
}

参考

確認環境

$ g++ -v
Apple clang version 15.0.0 (clang-1500.3.9.4)
Target: arm64-apple-darwin23.4.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?