ISO/ IEC JTC1/SC22/WG21 N4273

Document number: N4273
Date: 2014-11-06
Project: Programming Language C++, Library Working Group
Reply-to: Stephan T. Lavavej <stl@microsoft.com>


Uniform Container Erasure (Revision 2)


I. Introduction

This is a proposal to add erase_if(container, pred) and
erase(container, value), making it easier to eliminate unwanted elements
correctly and efficiently.  This updates N4161 (see [2]) by removing the
overloads of erase() for associative containers and unordered associative
containers, adding a Note about the missing overloads, and updating
[general.feature.test].  The original proposal N4009 (see [1]) explains
the rationale for this feature, which is not repeated here.


II. Standardese

1. In 1.3 [general.namespaces] Table 1 "C++ library headers", add:

<experimental/deque>
<experimental/forward_list>
<experimental/list>
<experimental/map>
<experimental/set>
<experimental/string>
<experimental/unordered_map>
<experimental/unordered_set>
<experimental/vector>

2. In 1.5 [general.feature.test] Table 2 "Significant features in this
technical specification", add:

         Doc. No.: N4273
            Title: Uniform Container Erasure
  Primary Section: [container.erasure]
Macro Name Suffix: erase_if
            Value: 201411
           Header: <experimental/vector>

3. Add a new section "Uniform container erasure" [container.erasure]
containing the following new sections.

4. Add a new section "Header synopsis" [container.erasure.syn] containing:

For brevity, this section specifies the contents of 9 headers, each of which
behaves as described by [general.namespaces].

namespace std {
namespace experimental {
inline namespace fundamentals_v2 {

  // [container.erasure.erase_if], function template erase_if
  // [container.erasure.erase], function template erase

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

} // inline namespace fundamentals_v2
} // namespace experimental
} // namespace std

5. Add a new section "Function template erase_if" [container.erasure.erase_if]
containing:

template <class charT, class traits, class A, class Predicate>
  void erase_if(basic_string<charT, traits, A>& c, Predicate pred);
template <class T, class A, class Predicate>
  void erase_if(deque<T, A>& c, Predicate pred);
template <class T, class A, class Predicate>
  void erase_if(vector<T, A>& c, Predicate pred);
Effects: Equivalent to:
  c.erase(remove_if(c.begin(), c.end(), pred), c.end());

template <class T, class A, class Predicate>
  void erase_if(forward_list<T, A>& c, Predicate pred);
template <class T, class A, class Predicate>
  void erase_if(list<T, A>& c, Predicate pred);
Effects: Equivalent to:
  c.remove_if(pred);

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);
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);
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);
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);
Effects: Equivalent to:
  for (auto i = c.begin(), last = c.end(); i != last; ) {
    if (pred(*i)) {
      i = c.erase(i);
    } else {
      ++i;
    }
  }

6. Add a new section "Function template erase" [container.erasure.erase]
containing:

template <class charT, class traits, class A, class U>
  void erase(basic_string<charT, traits, A>& c, const U& value);
template <class T, class A, class U>
  void erase(deque<T, A>& c, const U& value);
template <class T, class A, class U>
  void erase(vector<T, A>& c, const U& value);
Effects: Equivalent to:
  c.erase(remove(c.begin(), c.end(), value), c.end());

template <class T, class A, class U>
  void erase(forward_list<T, A>& c, const U& value);
template <class T, class A, class U>
  void erase(list<T, A>& c, const U& value);
Effects: Equivalent to:
  erase_if(c, [&](auto& elem) { return elem == value; });

[ Note: Overloads of erase() for associative containers and
unordered associative containers are intentionally not provided. --end note ]


III. References

All of the Library Fundamentals v2 citations in this proposal are to
Working Draft N4084:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4084.html

[1] N4009 "Uniform Container Erasure" by Stephan T. Lavavej:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4009.htm

[2] N4161 "Uniform Container Erasure (Revision 1)" by Stephan T. Lavavej:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4161.htm

(end)