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) | (since C++20) (until C++26) |
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 = {} );
|
(since 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 = {} );
|
(2) | (since C++20) (until C++26) |
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 = {} );
|
(since 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 = {} );
|
(3) | (since C++20) |
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 = {} );
|
(4) | (since 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 사후 조건에 따라).
이 페이지에 설명된 함수형 개체는 알고리즘 함수 객체 (비공식적으로 niebloids라고 함)이며, 즉:
- 이들 중 하나를 호출할 때 명시적 템플릿 인자 목록을 지정할 수 없습니다.
- 그들 중 어느 것도 인자 종속 조회에 보이지 않습니다.
- 그들 중 하나가 함수 호출 연산자 왼쪽의 이름으로 정규 비한정 조회에 의해 발견되면, 인자 종속 조회가 억제됩니다.
매개변수
| first, last | - | 처리할 요소들의 범위 를 정의하는 반복자-감시자 쌍 |
| r | - | 처리할 요소들의 범위 |
| value | - | 제거할 요소의 값 |
| pred | - | 투영된 요소들에 적용할 조건자 |
| proj | - | 요소들에 적용할 투영 |
반환값
{
ret, last
}
, 여기서
[
first
,
ret
)
는 제거 후 결과적인 부분 범위이며, 부분 범위
[
ret
,
last
)
내의 요소들은 모두 유효하지만 지정되지 않은 상태에 있습니다. 즉,
[
ret
,
last
)
는 삭제될 부분 범위입니다.
복잡도
정확히 N 번의 해당 predicate와 모든 projection이 적용되며, 여기서 N = ranges:: distance ( first, last ) 입니다. 또한 최악의 경우 N - 1 번의 move 연산이 수행됩니다.
참고 사항
ranges::remove
에 대한 호출은 일반적으로 컨테이너의
erase
멤버 함수 호출이 뒤따르며, 이는 지정되지 않은 값을 지우고 컨테이너의
물리적
크기를 새로운
논리적
크기에 맞게 축소합니다. 이 두 가지 호출을 함께 사용하면 소위
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) |
|---|
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) | 목록 초기화 for algorithms ( 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(v1) << " (v1, 크기: " << v1.size() << ")\n"; const auto ret = std::ranges::remove(v1, ' '); std::cout << std::quoted(v1) << " (v1 after `remove`, size: " << 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 `erase` 이후, 크기: " << 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(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)
|
범위에서 연속된 중복 요소들을 제거합니다
(알고리즘 함수 객체) |
|
특정 조건을 만족하는 요소들을 제거합니다
(함수 템플릿) |