4048. Inconsistent preconditions for transparent insertion of std::flat_map/std::flat_set

Section: 23.6.11 [flat.set], 23.6.8.1 [flat.map.overview] Status: New Submitter: Jiang An Opened: 2024-01-26 Last modified: 2024-03-15

Priority: 2

View all issues with New status.

Discussion:

The preconditions for transparent insertion of associative containers (23.4.3.4 [map.modifiers]/13, 23.4.3.4 [map.modifiers]/29, and 23.4.6.4 [set.modifiers]/3) detect the results of equal_range, while those for std::flat_set and std::flat_map (23.6.11.5 [flat.set.modifiers]/2 and 23.6.8.7 [flat.map.modifiers]/20) currently detect the results of find, which is inconsistent.

During implementing std::flat_set in MSVC STL, it was reported (microsoft/STL#4105) that the current preconditions for std::flat_set::insert can lead to inconsistent results. Tim Song told that the current preconditions were copied from old revisions of P2363. So, presumably we should change these preconditions for flat container adaptors to consistently use equal_range.

[2024-03-15; Reflector poll]

Set priority to 2 after reflector poll.

We didn't want equal_range(k) == equal_range(u) because the two sides of the == need to be evaluated at different times.

It seems to me that equal_range(k) == equal_range(u) ought to be true before the insertion, and still true after the insertion. The wording in 23.4.6.4 [set.modifiers]/3 and 23.4.3.4 [map.modifiers]/13 requires only that the condition be true before the insertion. We either want to change the wording here to be consistent with those places; or else change 23.4.6.4 [set.modifiers] and 23.4.3.4 [map.modifiers] to be consistent with the saner wording here. I'd vote for the latter.

Proposed resolution:

This wording is relative to N4971.

  1. Modify 23.6.8.7 [flat.map.modifiers] as indicated:

    template<class K, class... Args>
      pair<iterator, bool> try_emplace(K&& k, Args&&... args);
    template<class K, class... Args>
      iterator try_emplace(const_iterator hint, K&& k, Args&&... args);
    

    […]

    -20- Preconditions: The conversion from k into key_type constructs an object u, for which find(k) == find(u)equal_range(k) == equal_range(u) is true.

  2. Modify 23.6.11.5 [flat.set.modifiers] as indicated:

    template<class K> pair<iterator, bool> insert(K&& x);
    template<class K> iterator insert(const_iterator hint, K&& x);
    

    […]

    -2- Preconditions: The conversion from x into value_type constructs an object u, for which find(x) == find(u)equal_range(x) == equal_range(u) is true.