名前空間
変種
操作

std::remove, std::remove_if

From cppreference.com
< cpp‎ | algorithm
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとRangeアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
実行ポリシー (C++17)
シーケンスを変更しない操作
一括操作
(C++17)
検索操作
(C++11)                (C++11)(C++11)

シーケンスを変更する操作
コピー操作
(C++11)
(C++11)
スワップ操作
変換操作
生成操作
削除操作
removeremove_if
順序変更操作
(C++17まで)(C++11)
(C++20)(C++20)
サンプリング操作
(C++17)

ソートおよび関連操作
パーティション操作
ソート操作
二分探索操作
(パーティション化された範囲)
集合操作 (ソート済み範囲)
マージ操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作
Cライブラリ
数値演算
未初期化メモリに対する操作
 
ヘッダー <algorithm> で定義
(1)
template< class ForwardIt, class T >
ForwardIt remove( ForwardIt first, ForwardIt last, const T& value );
(C++20 以降 constexpr)
(C++26まで)
template< class ForwardIt, class T = typename std::iterator_traits

                                         <ForwardIt>::value_type >
constexpr ForwardIt remove( ForwardIt first, ForwardIt last,

                            const T& value );
(C++26以降)
(2)
template< class ExecutionPolicy, class ForwardIt, class T >

ForwardIt remove( ExecutionPolicy&& policy,

                  ForwardIt first, ForwardIt last, const T& value );
(C++17以降)
(C++26まで)
template< class ExecutionPolicy, class ForwardIt,

          class T = typename std::iterator_traits
                        <ForwardIt>::value_type >
ForwardIt remove( ExecutionPolicy&& policy,

                  ForwardIt first, ForwardIt last, const T& value );
(C++26以降)
template< class ForwardIt, class UnaryPred >
ForwardIt remove_if( ForwardIt first, ForwardIt last, UnaryPred p );
(3) (C++20 以降 constexpr)
template< class ExecutionPolicy, class ForwardIt, class UnaryPred >

ForwardIt remove_if( ExecutionPolicy&& policy,

                     ForwardIt first, ForwardIt last, UnaryPred p );
(4) (C++17以降)

指定された条件を満たす要素を範囲 [firstlast) から削除し、範囲の新しい終端を示すイテレータを返します。

1) value と等しいすべての要素を削除します(operator== を使用)。
3) 述語 ptrue を返すすべての要素を削除します。
2,4) (1,3)と同じだが、policyに従って実行される。
これらのオーバーロードは、以下のすべての条件が満たされた場合にのみオーバーロード解決に参加する。

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>true である。

(C++20まで)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>true です。

(C++20以降)


ForwardIt の値の型が CopyAssignable でない場合、動作は未定義です。

(C++11まで)

*first の型が MoveAssignable でない場合、動作は未定義です。

(C++11以降)

目次

[edit] 説明

削除は、削除されない要素が範囲の先頭に現れるように、範囲内の要素をシフトすることによって行われます。

  • シフトは コピー代入(C++11 まで)ムーブ代入(C++11 以降) によって行われます。
  • 削除操作は安定です。削除されない要素の相対順序は変更されません。
  • [firstlast) の基となるシーケンスは、削除操作によって短縮されません。返されるイテレータを result とすると
  • [resultlast) の各要素は、有効だが未指定の状態を持ちます。これは、ムーブ代入がその範囲内の元の要素から移動することによって要素を削除できるためです。
(C++11以降)

[edit] パラメータ

first, last - 処理する要素の 範囲 を定義するイテレータのペア
value - 削除する要素の値
policy - 使用する 実行ポリシー
p - 要素を削除すべき場合に ​true を返す単項述語。

ForwardIt の値の型 VT(おそらく const)のすべての引数 v に対して、p(v)bool に変換可能であり、値カテゴリに関係なく v を変更しない必要があります。したがって、VT& というパラメータ型は許可されません。また、VT がムーブがコピーと同等である場合を除き、VT も同様です(C++11 以降)

型要件
-
ForwardItLegacyForwardIterator の要件を満たさなければなりません。
-
UnaryPredicatePredicate の要件を満たさなければなりません。

[edit] 戻り値

新しい値の範囲を示す終端イテレータ(これが end でない場合、未指定の値を示し、このイテレータと end の間の値に対するイテレータも同様です)。

[edit] 計算量

std::distance(first, last)N とする

1,2) N 回の operator== による比較。
3,4) 述語 pN 回の適用。

[edit] 例外

ExecutionPolicy というテンプレートパラメータを持つオーバーロードは、次のようにエラーを報告します。

  • アルゴリズムの一部として呼び出された関数の実行が例外をスローし、ExecutionPolicy標準ポリシー のいずれかである場合、std::terminate が呼び出されます。その他の ExecutionPolicy の場合、動作は実装定義です。
  • アルゴリズムがメモリの割り当てに失敗した場合、std::bad_alloc がスローされます。

[edit] 実装例

remove (1)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type>
ForwardIt remove(ForwardIt first, ForwardIt last, const T& value)
{
    first = std::find(first, last, value);
    if (first != last)
        for (ForwardIt i = first; ++i != last;)
            if (!(*i == value))
                *first++ = std::move(*i);
    return first;
}
remove_if (3)
template<class ForwardIt, class UnaryPred>
ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p)
{
    first = std::find_if(first, last, p);
    if (first != last)
        for (ForwardIt i = first; ++i != last;)
            if (!p(*i))
                *first++ = std::move(*i);
    return first;
}

[edit] 注記

remove の呼び出しの後には、通常、コンテナから要素を実際に削除するためのコンテナの erase メンバ関数の呼び出しが続きます。この 2 つの呼び出しを組み合わせたものが、いわゆる erase-remove イディオムです。

同様の効果は、次の非メンバ関数でも達成できます。

(C++20以降)

同様の名前を持つコンテナの メンバ関数である list::removelist::remove_ifforward_list::remove、および forward_list::remove_if は、削除された要素を削除します。

これらのアルゴリズムは、std::setstd::map のような連想コンテナには使用できません。これは、これらのコンテナのイテレータ型が MoveAssignable 型をデリファレンスしないためです(これらのコンテナのキーは変更できません)。

標準ライブラリは、<cstdio>std::remove のオーバーロードも定義しています。これは const char* を取り、ファイルの削除に使用されます。

std::removevalue を参照で受け取るため、それが範囲 [firstlast) の要素への参照である場合、予期しない動作を引き起こす可能性があります。

機能テストマクロ 規格 機能
__cpp_lib_algorithm_default_value_type 202403 (C++26) アルゴリズム (1,2) のためのリスト初期化

[edit]

次のコードは、文字列からすべてのスペースを削除します。これは、スペース以外のすべての文字を左にシフトしてから、余分な文字を削除することによって行われます。これは erase-remove イディオムの例です。

#include <algorithm>
#include <cassert>
#include <cctype>
#include <complex>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
 
int main()
{
    std::string str1{"Quick  Red  Dog"};
    std::cout << "1) " << std::quoted(str1) << '\n';
    const auto noSpaceEnd = std::remove(str1.begin(), str1.end(), ' ');
    std::cout << "2) " << std::quoted(str1) << '\n';
 
    // The spaces are removed from the string only logically.
    // Note, we use view, the original string is still not shrunk:
    std::cout << "3) " << std::quoted(std::string_view(str1.begin(), noSpaceEnd))
              << ", size: " << str1.size() << '\n';
 
    str1.erase(noSpaceEnd, str1.end());
    // The spaces are removed from the string physically.
    std::cout << "4) " << std::quoted(str1) << ", size: " << str1.size() << '\n';
 
    std::string str2 = "Jumped\n Over\tA\vLazy \t  Fox\r\n";
    str2.erase(std::remove_if(str2.begin(), 
                              str2.end(),
                              [](unsigned char x) { return std::isspace(x); }),
               str2.end());
    std::cout << "5) " << std::quoted(str2) << '\n';
 
    std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}};
    #ifdef __cpp_lib_algorithm_default_value_type
        nums.erase(std::remove(nums.begin(), nums.end(), {1, 3}), nums.end());
    #else
        nums.erase(std::remove(nums.begin(), nums.end(), std::complex<double>{1, 3}),
                   nums.end());
    #endif
    assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}}));
}

出力

1) "Quick  Red  Dog"
2) "QuickRedDog Dog"
3) "QuickRedDog", size: 15
4) "QuickRedDog", size: 11
5) "JumpedOverALazyFox"

[edit] 不具合報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
LWG 283 C++98 TEqualityComparable であることが求められていましたが、
ForwardIt の値の型は常に T ではない
ForwardIt の値の型が
代わりに CopyAssignable である必要がある

[edit] 関連項目

特定の基準を満たす要素を除外して範囲をコピーする
(関数テンプレート) [編集]
範囲内の連続する重複要素を削除する
(関数テンプレート) [編集]
特定の基準を満たす要素を削除する
(アルゴリズム関数オブジェクト)[編集]
English 日本語 中文(简体) 中文(繁體)