为什么没有std :: erase?

时间:2018-07-19 10:39:36

标签: 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());

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

3 个答案:

答案 0 :(得分:28)

它如何工作?它仅接受一对迭代器。迭代器没有保留对其容器的引用(向量的迭代器可以仅仅是指针的别名)。

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

它必须是成员函数。

答案 1 :(得分:12)

http://jsbin.com/dotames/edit?html,js,output已于2014年底添加到std / experimental int图书馆基础知识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>

这些是来自Uniform container erasure的签名:

  // <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);

答案 2 :(得分: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, " "));

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

但是,当从容器中删除元素时,这有一定的局限性。

在利用(std-)算法的同时这样做是很常见的,足以使erase remove idiom成为众所周知的模式或范围库,可以利用整个容器的传递算法:

#include <boost/range/algorithm_ext.hpp>

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

boost::remove_erase(vec, 3);

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