std::ranges::remove, std::ranges::remove_if
| ヘッダ <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 を返します。ここで
value std::invoke(proj, *i) == value を用いて比較し、std::invoke(pred, std::invoke(proj, *i)) true を返すすべての要素を除去します。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 (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
関連項目
|
(C++20)
(C++20)
|
特定の条件を満たす要素を除外して範囲をコピーする
(アルゴリズム関数オブジェクト) |
|
(C++20)
|
範囲内の連続した重複要素を削除する
(アルゴリズム関数オブジェクト) |
|
特定の条件を満たす要素を削除する
(関数テンプレート) |