This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4219. std::vector::erase[_if] should be based on ranges remove

Section: 23.3.13.6 [vector.erasure] Status: New Submitter: Peter Kasting Opened: 2025-03-05 Last modified: 2025-03-09

Priority: Not Prioritized

View all issues with New status.

Discussion:

C++20 added std::vector::erase[_if]. Per 23.3.13.6 [vector.erasure], these are equivalent to a call to std::remove[_if] followed by an appropriate erase.

This is unfortunate, because std::remove_if is specified (by 26.7.8 [alg.remove]) as invoking its predicate as pred(*i), while std::ranges::remove_if uses the more flexible invoke(pred, invoke(proj, *i)). Disregarding the projection, the latter allows the use of member function pointers as predicates, while the former does not.

I assume the committee intentionally did not change the non-ranges version to use invoke because it caused a backwards-compatibility risk. (If I am mistaken and this was an oversight, perhaps this and other non-ranges algorithms that take predicates should be updated to use invoke() to invoke them.)

If that's true, though, it's perplexing why a new-to-c++20 function like std::vector::erase_if should suffer the same drawback.

Proposed resolution:

This wording is relative to N5001.

  1. Modify 23.3.13.6 [vector.erasure] as indicated:

    template<class T, class Allocator, class U = T>
      constexpr typename vector<T, Allocator>::size_type
        erase(vector<T, Allocator>& c, const U& value);
    

    -1- Effects: Equivalent to:

    auto rit = ranges::remove(c.begin(), c.end(), value);
    auto r = distance(it, c.end());
    c.erase(r.begin()it, rc.end());
    return r.size();
    
    template<class T, class Allocator, class Predicate>
      constexpr typename vector<T, Allocator>::size_type
        erase_if(vector<T, Allocator>& c, Predicate pred);
    

    -2- Effects: Equivalent to:

    auto rit = ranges::remove_if(c.begin(), c.end(), pred);
    auto r = distance(it, c.end());
    c.erase(r.begin()it, rc.end());
    return r.size();