Namespaces
Variants

std::ranges::remove, std::ranges::remove_if

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲に対するアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
ソートと関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割済み範囲に対する)
集合操作(ソート済み範囲に対する)
マージ操作(ソート済み範囲に対する)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書式比較操作
順列操作


 
制約付きアルゴリズム
このメニューのすべての名前は名前空間 std::ranges
に所属します
変更シーケンス操作
分割操作
ソート操作
二分探索操作(ソート済み範囲に対する)
       
       
集合操作(ソート済み範囲に対する)
ヒープ操作
最小値/最大値操作
       
       
順列操作
フォールド操作
数値操作
(C++23)            
未初期化ストレージに対する操作
戻り値型
 
ヘッダ <algorithm>
で定義
template< std::permutable I, std::sentinel_for<I> S,
          class T, class Proj = std::identity >
requires std::indirect_binary_predicate
             <ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>
    remove( I first, S last, const T& value, Proj proj = {} );
呼び出しシグネチャ (1)
(C++20以降)
template< std::permutable I, std::sentinel_for<I> S,
          class Proj = std::identity,
          class T = std::projected_value_t<I, Proj> >
requires std::indirect_binary_predicate
             <ranges::equal_to, std::projected<I, Proj>, const T*>
constexpr ranges::subrange<I>
    remove( I first, S last, const T& value, Proj proj = {} );
(C++26まで)
template< ranges::forward_range R,
          class T, class Proj = std::identity >
requires std::permutable<ranges::iterator_t<R>> &&
         std::indirect_binary_predicate
             <ranges::equal_to,
              std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_subrange_t<R>
    remove( R&& r, const T& value, Proj proj = {} );
(C++26以降) (2)
(C++20以降)
template< ranges::forward_range R,
          class Proj = std::identity,
          class T = std::projected_value_t<ranges::iterator_t<R>, Proj> >
requires std::permutable<ranges::iterator_t<R>> &&
         std::indirect_binary_predicate
             <ranges::equal_to,
              std::projected<ranges::iterator_t<R>, Proj>, const T*>
constexpr ranges::borrowed_subrange_t<R>
    remove( R&& r, const T& value, Proj proj = {} );
(C++26まで)
template< std::permutable I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr ranges::subrange<I>
    remove_if( I first, S last, Pred pred, Proj proj = {} );
(C++26以降) (3)
template< ranges::forward_range R,
          class Proj = std::identity,
          std::indirect_unary_predicate
              <std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>
    remove_if( R&& r, Pred pred, Proj proj = {} );
(C++20以降) (4)

(C++20以降)[first, last)範囲 [ret, last) から特定の条件を満たすすべての要素を除去し、部分範囲 ret を返します。ここで

は範囲の新しい終端を指す終端イテレータです。 1)value std::invoke(proj, *i) == value を用いて比較し、
に等しいすべての要素を除去します。3)std::invoke(pred, std::invoke(proj, *i)) true を返すすべての要素を除去します。
2,4) (1,3) と同じですが、r を範囲として使用し、ranges::begin(r) を first として、ranges::end(r) を last として使用したかのように動作します。

除去は、範囲内の要素を(ムーブ代入により)シフトすることで行われ、除去されない要素が範囲の先頭に現れるようにします。残った要素の相対的な順序は保持され、コンテナの物理的なサイズは変わりません。新しい論理的な終端と範囲の物理的な終端の間の要素を指すイテレータは依然として間接参照可能ですが、要素自体の値は不定です(MoveAssignableの事後条件に従います)。

このページで説明されている関数のようなエンティティはアルゴリズム関数オブジェクト(非公式にはniebloidとして知られています)であり、つまり次のようになります:

  • それらのいずれかを呼び出すときに明示的なテンプレート引数リストを指定することはできません。
  • それらは引数依存の名前検索では可視ではありません。
  • 通常の名前検索で関数呼び出し演算子の左側の名前として見つかった場合、引数依存の名前検索は抑制されます。引数依存の名前検索は抑制されます。

パラメータ

first, last - 処理対象の要素の範囲を定義する レンジ を表すイテレータ-番兵ペア
r - 処理対象の要素の範囲
value - 削除する要素の値
pred - 投影された要素に適用する述語
proj - 要素に適用する投影

戻り値

{ ret, last } 、ここで [ first , ret ) は除去後の結果サブレンジであり、サブレンジ [ ret , last ) 内の要素は全て有効だが未規定の状態、すなわち [ ret , last ) は削除対象のサブレンジです。

計算量

対応する述語と任意の射影の適用は正確に N 回行われ、ここで N = ranges:: distance ( first, last ) であり、最悪の場合 N - 1 回のムーブ操作が行われます。

注記

ranges::removeの呼び出しは通常、コンテナのeraseメンバ関数の呼び出しが続きます。これにより未規定の値が削除され、コンテナの物理的サイズが新しい論理的サイズに合わせて縮小されます。これら2つの呼び出しを組み合わせたものが、いわゆるerase-remove idiomであり、これはすべての標準シーケンスコンテナに対してオーバーロードを持つフリー関数std::erase、またはすべての標準コンテナに対してオーバーロードを持つstd::erase_ifによって実現できます。

同様の名称を持つコンテナ メンバー関数 list::remove 、 list::remove_if 、 forward_list::remove および forward_list::remove_if は削除された要素を消去します。

これらのアルゴリズムは通常、 std::set や std::map のような連想コンテナでは使用できません。なぜなら、これらのイテレータ型は MoveAssignable 型を参照解除しないためです(これらのコンテナのキーは変更不可能です)。

ranges::removeは value を参照で受け取るため、これが範囲 [ first , last ) の要素への参照である場合、予期せぬ動作を引き起こす可能性があります。

実装例

**日本語訳:** **翻訳説明:** - "remove" を「削除」と翻訳しました - HTMLタグ、属性、リンク先はそのまま保持しています - 括弧内の数字(1,2)は変更していません - C++の関数名としての"remove"は専門用語ですが、この文脈では一般的な操作名として翻訳するのが適切と判断しました HTMLタグ、属性、および``、`
`、``タグ内のテキストは翻訳せず、元のフォーマットを保持しました。C++固有の用語も翻訳していません。
**注記**: 提供されたHTMLコードはC++のコードスニペットを含んでおり、指示に従って以下の点を厳格に守りました: - HTMLタグと属性は一切翻訳せず - ``, `
`, ``タグ内のテキストは翻訳せず
- C++固有の用語(std::permutable, ranges::subrange, constexprなど)は翻訳せず
- 元のフォーマットを完全に保持

コード部分は全て原文のまま保持されています。
remove (1,2)
削除 (1,2)
struct remove_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             class T = std::projected_value_t<I, Proj>>
    requires std::indirect_binary_predicate
                 <ranges::equal_to, std::projected<I, Proj>, const T*>
    constexpr ranges::subrange<I>
        operator()(I first, S last, const T& value, Proj proj = {}) const
    {
        first = ranges::find(std::move(first), last, value, proj);
        if (first != last)
        {
            for (I i{std::next(first)}; i != last; ++i)
                if (value != std::invoke(proj, *i))
                {
                    *first = ranges::iter_move(i);
                    ++first;
                }
        }
        return {first, last};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             class T = std::projected_value_t<ranges::iterator_t<R>, Proj>>
    requires std::permutable<ranges::iterator_t<R>> &&
             std::indirect_binary_predicate
                 <ranges::equal_to,
                  std::projected<ranges::iterator_t<R>, Proj>, const T*>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, const T& value, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), value, std::move(proj));
    }
};
inline constexpr remove_fn remove {};
remove_if (3,4)
struct remove_if_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr ranges::subrange<I>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        first = ranges::find_if(std::move(first), last, pred, proj);
        if (first != last)
        {
            for (I i{std::next(first)}; i != last; ++i)
                if (!std::invoke(pred, std::invoke(proj, *i)))
                {
                    *first = ranges::iter_move(i);
                    ++first;
                }
        }
        return {first, last};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_unary_predicate
                 <std::projected<ranges::iterator_t<R>, Proj>> Pred>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r), pred, std::move(proj));
    }
};
inline constexpr remove_if_fn remove_if {};

注記

機能テスト マクロ 値 標準 機能
__cpp_lib_algorithm_default_value_type 202403 (C++26) リスト初期化 アルゴリズム用 ( 1,2 )

例

#include <algorithm>
#include <cassert>
#include <complex>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
int main()
{
    std::string v1{"診断不要"};
    std::cout << std::quoted

(注:指示に従い、HTMLタグ・属性は翻訳せず、C++固有用語も翻訳していません。表示されるテキスト「std::quoted」はC++標準ライブラリの関数名であるため、そのまま保持しています)(v1) << " (v1, サイズ: " << v1.size() << ")\n";
    const auto ret = std::ranges::remove(v1, ' ');
    std::cout << std::quoted

(注:指示に従い、HTMLタグ・属性は翻訳せず、C++固有用語も翻訳していません。表示されるテキスト「std::quoted」はC++標準ライブラリの関数名であるため、そのまま保持しています)(v1) << " (`remove`後のv1、サイズ: " << v1.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v1.begin(), ret.begin()), '^') << '\n';
    v1.erase(ret.begin(), ret.end());
    std::cout << std::quoted(v1) << " (v1 after `erase`, size: " << v1.size() << ")\n\n";
    // カスタム単項述語を使用したremove_if:
    auto rm = [](char c) { return !std::isupper(c); };
    std::string v2{"Substitution Failure Is Not An Error"};
    std::cout << std::quoted

(注:指示に従い、HTMLタグ・属性は翻訳せず、C++固有用語も翻訳していません。表示されるテキスト「std::quoted」はC++標準ライブラリの関数名であるため、そのまま保持しています)(v2) << " (v2, サイズ: " << v2.size() << ")\n";
    const auto [first, last] = std::ranges::remove_if(v2, rm);
    std::cout << std::quoted(v2) << " (v2 after `remove_if`, size: " << v2.size() << ")\n";
    std::cout << ' ' << std::string(std::distance(v2.begin(), first), '^') << '\n';
    v2.erase(first, last);
    std::cout << std::quoted(v2) << " (v2 の `erase` 後、サイズ: " << v2.size() << ")\n\n";
    // `remove_if`によって変更されるコンテナへのビューを作成:
    for (std::string s : {"Small Object Optimization", "非型テンプレートパラメータ"})
        std::cout << std::quoted(s) << " => "
            << std::string_view{begin(s), std::ranges::remove_if(s, rm).begin()} << '\n';
    std::vector<std::complex<double>> nums{{2, 2}, {1, 3}, {4, 8}};
    #ifdef __cpp_lib_algorithm_default_value_type
        auto e = std::ranges::remove(nums, {1, 3}); // T が推論される
    #else
        auto e = std::ranges::remove(nums, std::complex<double>{1, 3});
    #endif
    nums.erase(e.begin(), e.end());
    assert((nums == std::vector<std::complex<double>>{{2, 2}, {4, 8}}));
}

出力例:

"No _ Diagnostic _ Required" (v1, サイズ: 26)
"No_Diagnostic_Requiredired" (v1 `remove`後, サイズ: 26)
 ^^^^^^^^^^^^^^^^^^^^^^
"No_Diagnostic_Required" (v1 `erase`後, サイズ: 22)
"Substitution Failure Is Not An Error" (v2, サイズ: 36)
"SFINAEtution Failure Is Not An Error" (v2 `remove_if`後, サイズ: 36)
 ^^^^^^
"SFINAE" (v2 `erase`後, サイズ: 6)
"Small Object Optimization" => SOO
"Non-Type Template Parameter" => NTTP

関連項目

特定の条件を満たす要素を除外して範囲をコピーする
(アルゴリズム関数オブジェクト)
範囲内の連続した重複要素を削除する
(アルゴリズム関数オブジェクト)
特定の条件を満たす要素を削除する
(関数テンプレート)