過去15年間で、C++では状況が劇的に変化しました。1994年7月、ジェネリックプログラミングのアイデアを組み込んだライブラリのAlexander Stepanovの提案は、ANSI/ISO委員会から最終承認を受けました。今日STLと呼ばれるこのライブラリは、その後標準C++ライブラリになりました。STLのストーリーは、その背後にあるアイデアと同じくらい魅力的であり、間違いなく読む価値があります。
std::remove_if()
あなたが見つけた機能は、C++の現代的なアイデンティティの一部となったこの哲学の単なる別の反映です。要するに、これは要素の任意のコンテナ(シーケンス)および任意の(aのように機能する)条件で機能するジェネリック関数です。このためには、関数に2つのことを提供する必要があります。
- 作業したい要素の範囲を区切る2つのイテレータ。
- また、要素で呼び出されたときに、要素が削除される場合はtrueを返し、それ以外の場合はfalseを返す述語。
結局のところ、この場合、必要な述語は平等の述語です。また、等式に基づいて要素を削除することは非常に一般的なタスクであるため、標準はstd::remove()
暗黙の等式述語を想定する関数も提供します。もちろん、要素が比較できることを確認する必要があります。
bool operator==(const MyClass& a, const MyClass& b)
{
// return true if the two are equal, and false otherwise.
}
次に、述語を使用して、次のタイプの要素を削除できますMyClass
。
std::remove(things.begin(), things.end(), *this); // if *this == elem
std::remove()
標準関数は、まだ作成されていないコンテナも含め、どのコンテナでも機能することを思い出してください。あらゆる種類のコンテナには独自の要素の削除方法があるため、この関数は、動作するコンテナの実装の詳細を知らなければ、実際に削除を実行することはできません。したがって、代わりに、std::remove()
関数は、「削除された」要素がコンテナの最後にあるように要素を交換します。次に、「削除された」連続する要素の最初の要素を指すイテレータを返します。
typedef std::list<MyClass>::iterator iter;
iter first_removed = std::remove(things.begin(), things.end(), *this);
最後に、特定のコンテナの削除関数を呼び出して要素を本当に削除します。この関数は、リスト内の1つの位置、または連続する要素の範囲で機能して、次のように削除します。
things.erase(first_removed, things.end());
この種のコードが1行で表示されることは珍しくありません。
things.erase(std::remove(things.begin(), things.end(), *this),
things.end());
これはすべて圧倒的で複雑に見えるかもしれませんが、いくつかの利点があります。一つには、この標準ライブラリの設計は動的計画法をサポートしています。また、標準ライブラリは、非常にスリムなインターフェイスを備えたコンテナと、さまざまな種類のコンテナで動作するいくつかの無料の関数を提供できます。これにより、コンテナをすばやく作成し、標準ライブラリのすべての機能をすぐに利用できるようになります。または、すべての標準コンテナー(既に作成されているコンテナーとまだ作成されていないコンテナー)で即座に機能するジェネリック関数をすばやく作成できます。