コンテナからコンテナを作る例として, 下記のような (フィボナッチ数列をメモ化を使って求める) コードがあるとする.
このコードでは 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