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

3879. erase_if for flat_{,multi}set is incorrectly specified

Section: 24.6.11.6 [flat.set.erasure], 24.6.12.6 [flat.multiset.erasure] Status: C++23 Submitter: Tim Song Opened: 2023-02-09 Last modified: 2023-11-22

Priority: Not Prioritized

View all issues with C++23 status.

Discussion:

The current specification of erase_if for flat_{,multi}set calls ranges::remove_if on the set, which is obviously incorrect — the set only present constant views of its elements.

[Issaquah 2023-02-09; LWG]

Move to Immediate for C++23

[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate → WP.]

Proposed resolution:

This wording is relative to N4928.

  1. Modify 24.6.11.6 [flat.set.erasure] as indicated:

    template<class Key, class Compare, class KeyContainer, class Predicate>
      typename flat_set<Key, Compare, KeyContainer>::size_type
        erase_if(flat_set<Key, Compare, KeyContainer>& c, Predicate pred);
    

    -1- Effects: Equivalent to:

    auto [erase_first, erase_last] = ranges::remove_if(c, pred);
    auto n = erase_last - erase_first;
    c.erase(erase_first, erase_last);
    return n;
    

    -1- Preconditions: Key meets the Cpp17MoveAssignable requirements.

    -2- Effects: Let E be bool(pred(as_const(e))). Erases all elements e in c for which E holds.

    -3- Returns: The number of elements erased.

    -4- Complexity: Exactly c.size() applications of the predicate.

    -5- Remarks: Stable (16.4.6.8 [algorithm.stable]). If an invocation of erase_if exits via an exception, c is in a valid but unspecified state (3.65 [defns.valid]).

    [Note 1: c still meets its invariants, but can be empty. — end note]

  2. Modify 24.6.12.6 [flat.multiset.erasure] as indicated:

    template<class Key, class Compare, class KeyContainer, class Predicate>
      typename flat_multiset<Key, Compare, KeyContainer>::size_type
        erase_if(flat_multiset<Key, Compare, KeyContainer>& c, Predicate pred);
    

    -1- Effects: Equivalent to:

    auto [erase_first, erase_last] = ranges::remove_if(c, pred);
    auto n = erase_last - erase_first;
    c.erase(erase_first, erase_last);
    return n;
    

    -1- Preconditions: Key meets the Cpp17MoveAssignable requirements.

    -2- Effects: Let E be bool(pred(as_const(e))). Erases all elements e in c for which E holds.

    -3- Returns: The number of elements erased.

    -4- Complexity: Exactly c.size() applications of the predicate.

    -5- Remarks: Stable (16.4.6.8 [algorithm.stable]). If an invocation of erase_if exits via an exception, c is in a valid but unspecified state (3.65 [defns.valid]).

    [Note 1: c still meets its invariants, but can be empty. — end note]