より自然な条件判定が可能になるcontains/starts_with/ends_with[C++ 23]
C++ 23では、より自然な条件判定が可能になるcontains/starts_with/ends_with関数が使えるようになりました。
これらの関数はもともと<algorithm>ヘッダで提供されていて、C++ 23でRange対応版が利用可能になったということです。
- contains:要素が含まれるか判定
- starts_with:先頭部分の要素が一致するか判定
- ends_with:末尾部分の要素が一致するか判定
これらの新しい関数によって、コードの表現力が向上し、特定の要素の存在、Rangeの先頭、または末尾の一致を簡潔に判定できるようになります。
例えば以下は、ベクターについて要素の存在確認、先頭部、末尾部の一致を判定する例です。
std::vector<int> v = {1, 2, 3, 4, 5}; // 元となるベクター
// 指定要素が含まれるか判定する
bool result = ranges::contains(v, 3);
cout << "3 is " << (result? "" : "not ") << "in vector." << endl;
// 3 is in vector.
// 先頭部が指定するベクターに一致するか判定する
bool result2 = ranges::starts_with(v, std::vector<int>{1, 2});
cout << "[1, 2] is " << (result2? "" : "not ") << "prefix of vector." << endl;
// [1, 2] is prefix of vector.
// 末尾部が指定するベクターに一致するか判定する
bool result3 = ranges::ends_with(v, std::vector<int>{4, 5});
cout << "[4, 5] is " << (result3? "" : "not ") << "suffix of vector." << endl;
// [4, 5] is suffix of vector.
C++20より前では、これらの判定を行うためには、std::findやstd::search、std::equalなどを組み合わせて実装する必要がありました。しかし、C++23で導入されたこれらの関数により、より自然な条件判定が可能になったわけです。
その他にも、C++ 23で利用可能になった関数には、以下もあります。
- contains_subrange:指定した部分列(サブレンジ)が存在するか判定
- find_last:指定した値が最後に現れる位置を検索し、そのイテレータを返す
- find_last_if:指定条件を満たす要素が最後に現れる位置を検索し、イテレータを返す
- find_last_if_not:指定条件を満たさない要素が最後に現れる位置を検索
Rangeからコンテナへの変換が簡単なstd::ranges::to[C++ 23]
C++ 23では、Rangeからコンテナへ容易に変換できるstd::ranges::to関数が使えるようになりました。
std::ranges::to関数は、Rangeによって処理されたデータを直接任意のコンテナへ変換する機能を提供します。これによって、「コンテナ→Range処理→Range処理→…→コンテナ」という一連の処理を遅延を伴うことなく実現できるようになります。
変換には、パイプラインの最後をto関数とするだけです。例えば以下は、整数のベクターを作成し、パイプラインで偶数のみ抽出、それを2乗する加工を施し、再びベクターに戻すという例です。
vector<int> v = {1, 2, 3, 4, 5};
auto result = v | views::filter([](int x) { return x % 2 == 0; })
| views::transform([](int x) { return x * x; })
| ranges::to<std::vector>(); // 結果をstd::vectorに変換
cout << "Resulting Vector: ";
for (const auto& value : result) {
cout << value << " ";
}
cout << endl; // Resulting Vector: 4 16
std::ranges::to<std::vector>を使用することで、パイプライン処理の最終結果をstd::vectorとして取得できます。
