Namespaces
Variants
Views
Actions

Difference between revisions of "Template:cpp/container/erase2"

From cppreference.com
m (deque too)
m (`= T` for inplace_vector: P2248R14, it also already present in N4988 (C++26 draft); +demo for `U = T`.)
 
(14 intermediate revisions by 3 users not shown)
Line 1: Line 1:
{{cpp/title|erase|erase_if {{petty|(std::{{{1|}}})}}}}
+
{{#vardefine:cont|{{{1|inplace_vector}}}}}<!--
{{#switch:{{{1}}}
+
-->{{cpp/title|erase|erase_if{{small|(std::{{#var:cont}})}}}}
 +
{{#switch:{{#var:cont}}
 
|basic_string={{cpp/string/basic_string/navbar}}
 
|basic_string={{cpp/string/basic_string/navbar}}
|#default={{cpp/container/{{{1}}}/navbar}}
+
|#default={{cpp/container/{{#var:cont}}/navbar}}
 
}}
 
}}
{{cpp/container/get_types|{{{1}}}}}
+
{{cpp/container/get types|{{#var:cont}}}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header|{{cpp/container/get_header|{{{1}}}}}}}
+
{{dcl header|{{cpp/container/get header|{{#var:cont}}}}}}
{{dcl|since=c++20|num=1|1=
+
{{#switch:{{#var:cont}}
 +
|inplace_vector=
 +
{{dcl|num=1|since=c++26|1=
 +
template< class T, std::size_t N, class U = T >
 +
constexpr typename std::inplace_vector<T, N>::size_type
 +
    erase( std::inplace_vector<T, N>& c, const U& value );
 +
}}
 +
{{dcl|num=2|since=c++26|
 +
template< class T, std::size_t N, class Pred >
 +
constexpr typename std::inplace_vector<T, N>::size_type
 +
    erase_if( std::inplace_vector<T, N>& c, Pred pred );
 +
}}
 +
|
 +
{{dcl rev multi|num=1|anchor=1
 +
|since1=c++20|dcl1=
 
template< {{#var:types}}, class U >
 
template< {{#var:types}}, class U >
{{#switch:{{{1}}}
+
{{#switch:{{#var:cont}}
|vector|basic_string=constexpr typename
+
|vector|basic_string=constexpr std::{{#var:cont}}
|#default=typename}} std::{{{1}}}<{{#var:types_short}}>::size_type
+
|#default= std::{{#var:cont}}}}<{{#var:types_short}}>::size_type
     erase( std::{{{1}}}<{{#var:types_short}}>& c, const U& value );
+
    erase( std::{{#var:cont}}<{{#var:types_short}}>& c, const U& value );
 +
|since2=c++26|dcl2=
 +
template< {{#var:types}}, class U = {{#var:type_def}} >
 +
{{#switch:{{#var:cont}}
 +
|vector|basic_string=constexpr std::{{#var:cont}}
 +
|#default= std::{{#var:cont}}}}<{{#var:types_short}}>::size_type
 +
     erase( std::{{#var:cont}}<{{#var:types_short}}>& c, const U& value );
 
}}
 
}}
 
{{dcl|since=c++20|num=2|1=
 
{{dcl|since=c++20|num=2|1=
 
template< {{#var:types}}, class Pred >
 
template< {{#var:types}}, class Pred >
{{#switch:{{{1}}}
+
{{#switch:{{#var:cont}}
|vector|basic_string=constexpr typename
+
|vector|basic_string=constexpr std::{{#var:cont}}
|#default=typename}} std::{{{1}}}<{{#var:types_short}}>::size_type
+
|#default= std::{{#var:cont}}}}<{{#var:types_short}}>::size_type
     erase_if( std::{{{1}}}<{{#var:types_short}}>& c, Pred pred );
+
     erase_if( std::{{#var:cont}}<{{#var:types_short}}>& c, Pred pred );
 +
}}
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
@1@ Erases all elements that compare equal to {{c|value}} from the container. {{#switch:{{{1|}}}
+
@1@ Erases all elements that compare equal to {{c|value}} from the container. {{#switch:{{#var:cont}}
|vector
+
 
|basic_string
 
|basic_string
 +
|vector
 +
|inplace_vector
 
|deque=
 
|deque=
 
Equivalent to
 
Equivalent to
 
{{source|1=
 
{{source|1=
 
auto it = std::remove(c.begin(), c.end(), value);
 
auto it = std::remove(c.begin(), c.end(), value);
auto r = {{#switch:{{{1}}}|basic_string|deque|vector=c.end() - it|std::distance(it, c.end())}};
+
auto r = {{#switch:{{#var:cont}}|basic_string|deque|vector=c.end() - it|std::distance(it, c.end())}};
 
c.erase(it, c.end());
 
c.erase(it, c.end());
 
return r;
 
return r;
Line 36: Line 59:
 
|list
 
|list
 
|forward_list=
 
|forward_list=
Equivalent to {{c|1=return c.remove_if([&](auto& elem) { return elem == value; });}}
+
Equivalent to {{c|1=return c.remove_if([&](auto& elem) { return elem == value; });}}.
 
}}
 
}}
@2@ Erases all elements that satisfy the predicate {{c|pred}} from the container. {{#switch:{{{1}}}
+
@2@ Erases all elements that satisfy the predicate {{c|pred}} from the container. {{#switch:{{#var:cont}}
 
|vector
 
|vector
 +
|inplace_vector
 
|basic_string
 
|basic_string
 
|deque=
 
|deque=
Line 45: Line 69:
 
{{source|1=
 
{{source|1=
 
auto it = std::remove_if(c.begin(), c.end(), pred);
 
auto it = std::remove_if(c.begin(), c.end(), pred);
auto r = {{#switch:{{{1}}}|basic_string|deque|vector=c.end() - it|std::distance(it, c.end())}};
+
auto r = {{#switch:{{#var:cont}}|basic_string|deque|vector=c.end() - it|std::distance(it, c.end())}};
 
c.erase(it, c.end());
 
c.erase(it, c.end());
 
return r;
 
return r;
Line 51: Line 75:
 
|list
 
|list
 
|forward_list=
 
|forward_list=
Equivalent to {{c|1=return c.remove_if(pred);}}
+
Equivalent to {{c|1=return c.remove_if(pred);}}.
 
}}
 
}}
  
Line 58: Line 82:
 
{{par|c|container from which to erase}}
 
{{par|c|container from which to erase}}
 
{{par|value|value to be removed}}
 
{{par|value|value to be removed}}
{{par pred1|pred|if the element should be erased|t1={{#switch:{{{1}}}|basic_string=CharT|#default=T}}}}
+
{{par pred1|pred|if the element should be erased|t1={{#switch:{{#var:cont}}|basic_string=CharT|#default=T}}}}
 
{{par end}}
 
{{par end}}
  
Line 66: Line 90:
 
===Complexity===
 
===Complexity===
 
Linear.
 
Linear.
{{#switch:{{{1|}}}
+
<!---->
 +
{{#switch:{{#var:cont}}|inplace_vector=<!--nothing-->
 +
|
 +
===Notes===
 +
{{#switch:{{#var:cont}}
 
|list
 
|list
 
|forward_list=
 
|forward_list=
===Notes===
+
Unlike {{lc|std::{{#var:cont}}::remove}}, {{tt|erase}} accepts heterogeneous types and does not force a conversion to the container's value type before invoking the {{c|1===}} operator.
Unlike {{lc|std::{{{1|}}}::remove}}, {{tt|erase}} accepts heterogeneous types and does not force a conversion to the container's value type before invoking the {{c|1===}} operator.
+
}}
 +
{{feature test macro|__cpp_lib_algorithm_default_value_type|value=202403|std=C++26|[[cpp/language/list_initialization|List-initialization]] for algorithm {{vl|1}}}}
 
}}
 
}}
 +
<!---->
 
===Example===
 
===Example===
{{#switch:{{{1|}}}
+
{{#switch:{{#var:cont}}
 
|basic_string=
 
|basic_string=
 
{{example
 
{{example
Line 96: Line 126:
 
     std::cout << "After erase all 'a', 'r', and 't': " << std::quoted(word) << '\n';
 
     std::cout << "After erase all 'a', 'r', and 't': " << std::quoted(word) << '\n';
 
     std::cout << "Erased symbols count: " << erased << '\n';
 
     std::cout << "Erased symbols count: " << erased << '\n';
 +
 +
#if __cpp_lib_algorithm_default_value_type
 +
    std::erase(word, {'g'});
 +
    std::cout << "After erase {'g'}: " << std::quoted(word) << '\n';
 +
#endif
 
}
 
}
 +
|p=true
 
|output=
 
|output=
 
Initially, word = "startling"
 
Initially, word = "startling"
Line 102: Line 138:
 
After erase all 'a', 'r', and 't': "sing"
 
After erase all 'a', 'r', and 't': "sing"
 
Erased symbols count: 4
 
Erased symbols count: 4
 +
After erase {'g'}: "sin"
 +
}}
 +
|inplace_vector=
 +
{{example
 +
|code=
 +
#include <cassert>
 +
#include <complex>
 +
#include <inplace_vector>
 +
#include <numeric>
 +
#include <print>
 +
 +
int main()
 +
{
 +
    std::inplace_vector<int, 10> v(10, 0);
 +
    std::ranges::iota(v, 0);
 +
    std::println("Initially, v = {}", v);
 +
 +
    auto erased = std::erase(v, 3);
 +
    std::println("After erase(v, 3), v = {}", v);
 +
    assert(erased == 1);
 +
 +
    erased = std::erase_if(v, [](int x) { return x % 2 == 0; });
 +
    std::println("After erasing all even numbers, v = {}", v);
 +
    std::println("Erased even numbers: {}", erased);
 +
 +
    std::inplace_vector<std::complex<double>> nums{<!---->{2, 2}, {4, 2}, {4, 8}, {4, 2}<!---->};
 +
    std::erase(nums, {4, 2}); // since U = T, the value type can be ommited
 +
    std::println("After erase {4, 2}, nums = {}", nums);
 +
}
 +
|output=
 +
Initially, v = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
 +
After erase(v, 3), v = [0, 1, 2, 4, 5, 6, 7, 8, 9]
 +
After erasing all even numbers, v = [1, 5, 7, 9]
 +
Erased even numbers: 5
 +
After erase {4, 2}, nums = [(2,2), (4,8)]
 
}}
 
}}
 
|
 
|
 
{{example
 
{{example
 
|code=
 
|code=
 +
#include <complex>
 
#include <iostream>
 
#include <iostream>
 
#include <numeric>
 
#include <numeric>
 
#include <string_view>
 
#include <string_view>
#include <{{{1|list}}}>
+
#include <{{#var:cont}}>
  
void print_container(std::string_view comment, const std::{{{1|list}}}<char>& c)
+
void println(std::string_view comment, const auto& c)
 
{
 
{
     std::cout << comment << "{ ";
+
     std::cout << comment << '[';
     for (char x : c)
+
    bool first{true};
         std::cout << x << ' ';
+
     for (const auto& x : c)
     std::cout << "}\n";
+
         std::cout << (first ? first = false, "" : ", ") << x;
 +
     std::cout << "]\n";
 
}
 
}
  
 
int main()
 
int main()
 
{
 
{
     std::{{{1|list}}}<char> cnt(10);
+
     std::{{#var:cont}}<char> cnt(10);
 
     std::iota(cnt.begin(), cnt.end(), '0');
 
     std::iota(cnt.begin(), cnt.end(), '0');
     print_container("Initially, cnt = ", cnt);
+
     println("Initially, cnt = ", cnt);
  
 
     std::erase(cnt, '3');
 
     std::erase(cnt, '3');
     print_container("After erase '3', cnt = ", cnt);
+
     println("After erase '3', cnt = ", cnt);
  
 
     auto erased = std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
 
     auto erased = std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
     print_container("After erase all even numbers, cnt = ", cnt);
+
     println("After erase all even numbers, cnt = ", cnt);
 
     std::cout << "Erased even numbers: " << erased << '\n';
 
     std::cout << "Erased even numbers: " << erased << '\n';
 +
 +
    std::{{#var:cont}}<std::complex<double>> nums{<!---->{2, 2}, {4, 2}, {4, 8}, {4, 2}<!---->};
 +
    #ifdef __cpp_lib_algorithm_default_value_type
 +
        std::erase(nums, {4, 2});
 +
    #else
 +
        std::erase(nums, std::complex<double>{4, 2});
 +
    #endif
 +
    println("After erase {4, 2}, nums = ", nums);
 
}
 
}
 
|output=
 
|output=
Initially, cnt = { 0 1 2 3 4 5 6 7 8 9 }
+
Initially, cnt = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
After erase '3', cnt = { 0 1 2 4 5 6 7 8 9 }
+
After erase '3', cnt = [0, 1, 2, 4, 5, 6, 7, 8, 9]
After erase all even numbers, cnt = { 1 5 7 9 }
+
After erase all even numbers, cnt = [1, 5, 7, 9]
 
Erased even numbers: 5
 
Erased even numbers: 5
 +
After erase {4, 2}, nums = [(2,2), (4,8)]
 
}}
 
}}
 
}}
 
}}
Line 143: Line 225:
 
{{dsc begin}}
 
{{dsc begin}}
 
{{dsc inc|cpp/algorithm/dsc remove}}
 
{{dsc inc|cpp/algorithm/dsc remove}}
{{#switch:{{{1}}}
+
{{dsc inc|cpp/algorithm/ranges/dsc remove}}
 +
{{#switch:{{#var:cont}}
 
|list
 
|list
 
|forward_list=
 
|forward_list=
{{dsc inc|cpp/container/dsc remove|{{{1}}}}}
+
{{dsc inc|cpp/container/dsc remove|{{#var:cont}}}}
 
}}
 
}}
 
{{dsc end}}
 
{{dsc end}}

Latest revision as of 15:59, 22 September 2024

 
 
 
 
Defined in header <inplace_vector>
template< class T, std::size_t N, class U = T >

constexpr typename std::inplace_vector<T, N>::size_type

    erase( std::inplace_vector<T, N>& c, const U& value );
(1) (since C++26)
template< class T, std::size_t N, class Pred >

constexpr typename std::inplace_vector<T, N>::size_type

    erase_if( std::inplace_vector<T, N>& c, Pred pred );
(2) (since C++26)
1) Erases all elements that compare equal to value from the container. Equivalent to
auto it = std::remove(c.begin(), c.end(), value);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;
2) Erases all elements that satisfy the predicate pred from the container. Equivalent to
auto it = std::remove_if(c.begin(), c.end(), pred);
auto r = std::distance(it, c.end());
c.erase(it, c.end());
return r;

Contents

[edit] Parameters

c - container from which to erase
value - value to be removed
pred - unary predicate which returns ​true if the element should be erased.

The expression pred(v) must be convertible to bool for every argument v of type (possibly const) T, regardless of value category, and must not modify v. Thus, a parameter type of T&is not allowed, nor is T unless for T a move is equivalent to a copy(since C++11). ​

[edit] Return value

The number of erased elements.

[edit] Complexity

Linear.

[edit] Example

#include <cassert>
#include <complex>
#include <inplace_vector>
#include <numeric>
#include <print>
 
int main()
{
    std::inplace_vector<int, 10> v(10, 0);
    std::ranges::iota(v, 0);
    std::println("Initially, v = {}", v);
 
    auto erased = std::erase(v, 3);
    std::println("After erase(v, 3), v = {}", v);
    assert(erased == 1);
 
    erased = std::erase_if(v, [](int x) { return x % 2 == 0; });
    std::println("After erasing all even numbers, v = {}", v);
    std::println("Erased even numbers: {}", erased);
 
    std::inplace_vector<std::complex<double>> nums{{2, 2}, {4, 2}, {4, 8}, {4, 2}};
    std::erase(nums, {4, 2}); // since U = T, the value type can be ommited
    std::println("After erase {4, 2}, nums = {}", nums);
}

Output:

Initially, v = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
After erase(v, 3), v = [0, 1, 2, 4, 5, 6, 7, 8, 9]
After erasing all even numbers, v = [1, 5, 7, 9]
Erased even numbers: 5
After erase {4, 2}, nums = [(2,2), (4,8)]

[edit] See also

removes elements satisfying specific criteria
(function template) [edit]
removes elements satisfying specific criteria
(niebloid)[edit]