🏁 はじめに
前回投稿したerase + remove_if + ラムダ式の流れをまとめた関数が現代にはあるということをコメント欄で@shibainuudon様に教えていただきました。
その名もstd::erase_ifです!!!
前回の投稿から間が空いてしまいましたがやっとまとまった時間ができたので記事として残そうと思います。
"abcabcABC" から 'a' と 'b' を削除 → "ccABC"
これをスマートかつ効率的に実現できるのが、
std::remove_if() + std::string::erase() + ラムダ式
の組み合わせと前回お伝えしました。
だがしかし!!
色々組み合わせなくてもerase_ifで一発で自由に消せるみたいです。
🔍 remove_if + erase と std::erase_if の違い
| 項目 | remove_if + erase |
std::erase_if (C++20〜) |
|---|---|---|
| シンプルさ | 2段階の処理が必要でやや冗長 | ワンステップで書けてとてもシンプル |
| 標準ライブラリ対応 | C++11以降で利用可能 | C++20以降で利用可能 |
| 処理の中身 | 自分で remove_if と erase を組み合わせる |
ライブラリ内部で効率的に実装されている |
| 柔軟性 | ラムダ式で条件指定が自由 | 同様にラムダ式対応で柔軟 |
🧪 実行可能なサンプルコード
#include <iostream>
#include <string>
#include <algorithm> // std::erase_if はここにあるよ
int main() {
std::string str = "abcabcABC";
// 'a' と 'b' を削除
std::erase_if(str, [](char c) {
return c == 'a' || c == 'b';
});
std::cout << str << std::endl; // 出力: ccABC
return 0;
}
コード解説
このプログラムは「文字列の中から特定の文字を全部削除する」処理をしています。
具体的には、
- 最初の文字列は
"abcabcABC" - 消したい文字は
'a'と'b'です。
処理の流れは以下の通りです。
-
std::erase_ifという関数を使って、文字列の中を1文字ずつ調べます。 - もし文字が
'a'または'b'だったら、その文字を「削除する」と判断します。 - 削除すべき文字をまとめて文字列から消します。
- 最終的に残った文字だけが詰められて、結果として
"ccABC"という文字列になります。
この関数は、以前からある remove_if と erase を組み合わせる方法を一つにまとめてくれているので、
コードがとてもシンプルで読みやすくなっています。
✅ 使用メリット
-
対応コンテナ
std::erase_if は std::string だけじゃなく、std::vector や std::deque、std::list など標準コンテナ全般に使えます。
条件に合う要素を一括で削除できるので、いろんな場面で便利! -
パフォーマンス
内部は基本的に remove_if + erase の最適化バージョンなので、パフォーマンスはほぼ同じ。
ただ、ワンステップなのでコードがシンプルになる分、ミスも減ります。 -
可読性の向上
コードが1行で完結するので、可読性がかなり上がります。
メンテナンスやコードレビューで助かること間違いなし。 -
C++20以降の環境が必要
使うにはC++20対応のコンパイラが必要です。
例えば、GCC 10以降やClang 12以降、MSVCの最新バージョンなどで利用可能。 -
ラムダ以外も使える
条件はラムダ式が一般的だけど、関数オブジェクトや関数ポインタも使えます。
柔軟な条件指定ができます!!
〇 前回記事
前回は古いイディオムを紹介しました。
今回紹介したのが古いイディオムの進化版のような感じなのですが、比較したい方は是非読んでみてください。
https://qiita.com/fe1ix/items/27baa4664f1881676411
参考