为什么没有std :: erase?

Ami*_*ira 19 c++ stl

在阅读STL时,我意识到没有std::erase提供.我不确定为什么它不存在.一个有效的用例如下

std::vector<int> odd { 1, 3, 5, 3, 9, 11, 5, 17 };
std::sort(odd.begin(), odd.end());
std::erase(std::unique(odd.begin(), odd.end()), odd.end());
Run Code Online (Sandbox Code Playgroud)

它嵌入在每个容器中.如果性能是原因,那么如果对象是连续的,则可以一次删除它们.但我想这可以通过帮助模板专业化来实现.

Sto*_*ica 29

它会如何工作?它只接受一对迭代器.迭代器不具备继续履行其容器的引用(向量的迭代器可以是单纯的别名指针).

那么算法如何修改容器本身呢?它需要访问权限.

它必须是成员函数.


ems*_*msr 12

2014年底,在图书馆基础2 TS中添加了统一的容器擦除.这是最近投票的C++ - 2a的标准,但即使是github的草案也没有显示.我知道gcc,clang和Visual Studio支持实验.

因此,代替您通常的容器包括以下版本之一:

<experimental/deque>
<experimental/forward_list>
<experimental/list>
<experimental/map>
<experimental/set>
<experimental/string>
<experimental/unordered_map>
<experimental/unordered_set>
<experimental/vector>
Run Code Online (Sandbox Code Playgroud)

这些是来自最近的一篇论文的签名:

  // <experimental/string>
  template <class charT, class traits, class A, class Predicate>
    void erase_if(basic_string<charT, traits, A>& c, Predicate pred);
  template <class charT, class traits, class A, class U>
    void erase(basic_string<charT, traits, A>& c, const U& value);

  // <experimental/deque>
  template <class T, class A, class Predicate>
    void erase_if(deque<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(deque<T, A>& c, const U& value);

  // <experimental/vector>
  template <class T, class A, class Predicate>
    void erase_if(vector<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(vector<T, A>& c, const U& value);

  // <experimental/forward_list>
  template <class T, class A, class Predicate>
    void erase_if(forward_list<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(forward_list<T, A>& c, const U& value);

  // <experimental/list>
  template <class T, class A, class Predicate>
    void erase_if(list<T, A>& c, Predicate pred);
  template <class T, class A, class U>
    void erase(list<T, A>& c, const U& value);

  // <experimental/map>
  template <class K, class T, class C, class A, class Predicate>
    void erase_if(map<K, T, C, A>& c, Predicate pred);
  template <class K, class T, class C, class A, class Predicate>
    void erase_if(multimap<K, T, C, A>& c, Predicate pred);

  // <experimental/set>
  template <class K, class C, class A, class Predicate>
    void erase_if(set<K, C, A>& c, Predicate pred);
  template <class K, class C, class A, class Predicate>
    void erase_if(multiset<K, C, A>& c, Predicate pred);

  // <experimental/unordered_map>
  template <class K, class T, class H, class P, class A, class Predicate>
    void erase_if(unordered_map<K, T, H, P, A>& c, Predicate pred);
  template <class K, class T, class H, class P, class A, class Predicate>
    void erase_if(unordered_multimap<K, T, H, P, A>& c, Predicate pred);

  // <experimental/unordered_set>
  template <class K, class H, class P, class A, class Predicate>
    void erase_if(unordered_set<K, H, P, A>& c, Predicate pred);
  template <class K, class H, class P, class A, class Predicate>
    void erase_if(unordered_multiset<K, H, P, A>& c, Predicate pred);
Run Code Online (Sandbox Code Playgroud)

  • 它已添加到C ++ 20中,并且最近在gcc-9,clang-7,Visual studion中实现。 (2认同)

lub*_*bgr 7

序列和算法之间的粘合剂是迭代器(感谢@Pete Becker在这里指出了正确的术语).它们归结为可应用于多个序列(容器)类型的强大算法所需的最小功能.一个例子是这样一个片段:

std::vector<int> vec{1, 2, 3, 4};
std::list<int> lst;

std::copy(vec.cbegin(), vec.cend(), std::back_inserter(lst));
std::copy(lst.cbegin(), lst.cend(), std::ostream_iterator<int>(std::cout, " "));
Run Code Online (Sandbox Code Playgroud)

在这里,std::copy可以独立于它所操作的特定序列类型来实现,因为它与迭代器一起工作,这些迭代器要做两件事:遍历序列并提供对其元素的访问.

但是,当从容器中删除元素时,这具有限制.

在利用(std- )算法时这样做的必要性足以引起擦除删除习惯用法是一个众所周知的模式或范围库,它利用整个容器传递给算法:

#include <boost/range/algorithm_ext.hpp>

std::vector<int> vec{1, 2, 3, 4};

boost::remove_erase(vec, 3);
Run Code Online (Sandbox Code Playgroud)

最后一个函数调用实际上可以3从容器中删除带有值的元素,因为在该函数调用中没有隐藏任何信息.相比之下,*begin/ *end(成员)函数族完全相同:将信息隐藏在抽象之后.

  • 抽象比这更抽象.迭代器是**序列**和算法之间的粘合剂.容器是管理序列的一种方式,但它们不是唯一的方法.例如,您可以创建一对遍历输入流的迭代器; 很少有人会将输入流称为容器.+1无论如何. (4认同)