Namespaces
Variants
Views
Actions

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

From cppreference.com
m (Example)
m (`= T` for inplace_vector: P2248R14, it also already present in N4988 (C++26 draft); +demo for `U = T`.)
 
(34 intermediate revisions by 7 users not shown)
Line 1: Line 1:
{{cpp/title | erase | erase_if <small>(std::{{{1|}}})</small>}}
+
{{#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 >
void erase(std::{{{1}}}<{{#var:types_short}}>& c, const U& value);
+
{{#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 );
 +
|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 >
void erase_if(std::{{{1}}}<{{#var:types_short}}>& c, Pred pred);
+
{{#switch:{{#var:cont}}
 +
|vector|basic_string=constexpr std::{{#var:cont}}
 +
|#default= std::{{#var:cont}}}}<{{#var:types_short}}>::size_type
 +
    erase_if( std::{{#var:cont}}<{{#var:types_short}}>& c, Pred pred );
 +
}}
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
@1@ Erases all elements that compare equal to {{tt|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 {{c|c.erase(std::remove(c.begin(), c.end(), value), c.end());}}
+
Equivalent to
 +
{{source|1=
 +
auto it = std::remove(c.begin(), c.end(), value);
 +
auto r = {{#switch:{{#var:cont}}|basic_string|deque|vector=c.end() - it|std::distance(it, c.end())}};
 +
c.erase(it, c.end());
 +
return r;
 +
}}
 
|list
 
|list
 
|forward_list=
 
|forward_list=
Equivalent to {{c|1=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 {{tt|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=
Equivalent to {{c|c.erase(std::remove_if(c.begin(), c.end(), pred), c.end());}}
+
Equivalent to
 +
{{source|1=
 +
auto it = std::remove_if(c.begin(), c.end(), pred);
 +
auto r = {{#switch:{{#var:cont}}|basic_string|deque|vector=c.end() - it|std::distance(it, c.end())}};
 +
c.erase(it, c.end());
 +
return r;
 +
}}
 
|list
 
|list
 
|forward_list=
 
|forward_list=
Equivalent to {{c|1=c.remove_if(pred);}}
+
Equivalent to {{c|1=return c.remove_if(pred);}}.
 
}}
 
}}
  
 
===Parameters===
 
===Parameters===
 
{{par begin}}
 
{{par begin}}
{{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}}
 +
 
 +
===Return value===
 +
The number of erased elements.
  
 
===Complexity===
 
===Complexity===
 
Linear.
 
Linear.
 
+
<!---->
 +
{{#switch:{{#var:cont}}|inplace_vector=<!--nothing-->
 +
|
 +
===Notes===
 +
{{#switch:{{#var:cont}}
 +
|list
 +
|forward_list=
 +
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.
 +
}}
 +
{{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:{{#var:cont}}
 +
|basic_string=
 
{{example
 
{{example
| code=
+
|code=
 +
#include <iomanip>
 
#include <iostream>
 
#include <iostream>
 +
#include <string>
 +
 +
int main()
 +
{
 +
    std::string word{"startling"};
 +
    std::cout << "Initially, word = " << std::quoted(word) << '\n';
 +
 +
    std::erase(word, 'l');
 +
    std::cout << "After erase 'l': " << std::quoted(word) << '\n';
 +
 +
    auto erased = std::erase_if(word, [](char x)
 +
    {
 +
        return x == 'a' or x == 'r' or x == 't';
 +
    });
 +
 +
    std::cout << "After erase all 'a', 'r', and 't': " << std::quoted(word) << '\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=
 +
Initially, word = "startling"
 +
After erase 'l', word = "starting"
 +
After erase all 'a', 'r', and 't': "sing"
 +
Erased symbols count: 4
 +
After erase {'g'}: "sin"
 +
}}
 +
|inplace_vector=
 +
{{example
 +
|code=
 +
#include <cassert>
 +
#include <complex>
 +
#include <inplace_vector>
 
#include <numeric>
 
#include <numeric>
#include <{{#switch:{{{1}}}|basic_string=string|{{{1}}}}}>
+
#include <print>
  
void print_container(const std::{{#switch:{{{1}}}|basic_string=string|{{{1}}}<char>}}& c)
+
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
 +
|code=
 +
#include <complex>
 +
#include <iostream>
 +
#include <numeric>
 +
#include <string_view>
 +
#include <{{#var:cont}}>
 +
 
 +
void println(std::string_view comment, const auto& c)
 
{
 
{
     for (auto x : c) {
+
    std::cout << comment << '[';
         std::cout << x << ' ';
+
    bool first{true};
    }
+
     for (const auto& x : c)
     std::cout << '\n';
+
         std::cout << (first ? first = false, "" : ", ") << x;
 +
     std::cout << "]\n";
 
}
 
}
  
 
int main()
 
int main()
 
{
 
{
     std::{{#switch:{{{1}}}|basic_string=string cnt(10, ' ')|{{{1}}}<char> cnt(10)}};
+
     std::{{#var:cont}}<char> cnt(10);
 
     std::iota(cnt.begin(), cnt.end(), '0');
 
     std::iota(cnt.begin(), cnt.end(), '0');
 +
    println("Initially, cnt = ", cnt);
  
     std::cout << "Init:\n";
+
     std::erase(cnt, '3');
     print_container(cnt);
+
     println("After erase '3', cnt = ", cnt);
  
     std::erase(cnt, '5');
+
     auto erased = std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
     std::cout << "Erase \'5\':\n";
+
    println("After erase all even numbers, cnt = ", cnt);
    print_container(cnt);
+
     std::cout << "Erased even numbers: " << erased << '\n';
  
     std::erase_if(cnt, [](char x) { return (x - '0') % 2 == 0; });
+
     std::{{#var:cont}}<std::complex<double>> nums{<!---->{2, 2}, {4, 2}, {4, 8}, {4, 2}<!---->};
     std::cout << "Erase all even numbers:\n";
+
    #ifdef __cpp_lib_algorithm_default_value_type
     print_container(cnt);
+
        std::erase(nums, {4, 2});
 +
     #else
 +
        std::erase(nums, std::complex<double>{4, 2});
 +
     #endif
 +
    println("After erase {4, 2}, nums = ", nums);
 
}
 
}
| output=
+
|output=
Init:
+
Initially, cnt = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0 1 2 3 4 5 6 7 8 9  
+
After erase '3', cnt = [0, 1, 2, 4, 5, 6, 7, 8, 9]
Erase '5':
+
After erase all even numbers, cnt = [1, 5, 7, 9]
0 1 2 3 4 6 7 8 9  
+
Erased even numbers: 5
Erase all even numbers:
+
After erase {4, 2}, nums = [(2,2), (4,8)]
1 3 7 9
+
 
}}
 
}}
 
{{#switch:{{{1|}}}
 
|list
 
|forward_list=
 
=== Notes ===
 
Unlike {{lc|std::{{{1|}}}::remove}}, {{tt|erase}} accepts heterogenous types and does not force a conversion to the container's value type before invoking the {{c|{{==}}}} operator.
 
 
}}
 
}}
  
 
===See also===
 
===See also===
 
 
{{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]