4499. flat_set::insert_range specification may be problematic

Section: 23.6.11.5 [flat.set.modifiers], 23.6.12.5 [flat.multiset.modifiers] Status: Ready Submitter: Hewill Kang Opened: 2025-12-22 Last modified: 2026-02-20

Priority: 2

View all issues with Ready status.

Discussion:

The function adds elements via:

ranges::for_each(rg, [&](auto&& e) {
  c.insert(c.end(), std::forward<decltype(e)>(e));
});

Here, e is an element of the input range.

However, this can lead to ambiguity when e can also be converted to initializer_list, as vector::insert has an overload of insert(const_iterator, initializer_list<T>).

[2026-02-18; Reflector poll.]

Set priority to 2 after reflector poll.

Pessimizing a very common case (matching type), for uncommon one.

[2026-02-20; LWG telecon; Status changed: New → Ready.]

Implementations can optimize away the extra move for the case where the range's value type is already the same as the flat set's value type.

Proposed resolution:

This wording is relative to N5032.

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

    template<container-compatible-range<value_type> R>
      constexpr void insert_range(R&& rg);
    

    -10- Effects: Adds elements to c as if by:

    ranges::for_each(rg, [&](value_typeauto&& e) {
      c.insert(c.end(), std::movestd::forward<decltype(e)>(e));
    });
    
  2. Modify 23.6.12.5 [flat.multiset.modifiers] as indicated:

    template<container-compatible-range<value_type> R>
      void insert_range(R&& rg);
    

    -9- Effects: Adds elements to c as if by:

    ranges::for_each(rg, [&](value_typeauto&& e) {
      c.insert(c.end(), std::movestd::forward<decltype(e)>(e));
    });