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.

### 3802. `flat_foo` allocator-extended constructors lack move semantics

Section: 24.6.9 [flat.map], 24.6.10 [flat.multimap], 24.6.11 [flat.set], 24.6.12 [flat.multiset] Status: New Submitter: Arthur O'Dwyer Opened: 2022-10-25 Last modified: 2022-11-04

Priority: 2

View other active issues in [flat.map].

View all other issues in [flat.map].

View all issues with New status.

Discussion:

Compare 24.6.7.2 [priqueue.cons]'s overload set

>     priority_queue(const Compare&, const Container&);
>     priority_queue(const Compare&, Container&&);
>     template<class Alloc> priority_queue(const Compare&, const Container&, const Alloc&);
>     template<class Alloc> priority_queue(const Compare&, Container&&, const Alloc&);

against 24.6.9 [flat.map]'s overload set

>     flat_map(key_container_type, mapped_container_type);
>     template<class Allocator> flat_map(const key_container_type&, const mapped_container_type&, const Allocator& a);

I see two issues here:

1. (A) The allocator-extended ctor of `flat_map` always copies the `key_container` and `value_container`, when it should be move-enabled.

2. (B) Almost certainly the `Allocator` parameter should be named `Alloc` instead, and there should be a separate "Constructors with allocators" section with wording similar to 24.6.7.3 [priqueue.cons.alloc] explaining that these ctors don't participate in overload resolution unless `uses_allocator_v<KeyContainer, Alloc> && uses_allocator_v<MappedContainer, Alloc>`.

I suggest this overload set to replace the two overloads above:

>     flat_map(key_container_type, mapped_container_type);
>     template<class Alloc> flat_map(const key_container_type&, const mapped_container_type&, const Alloc& a);
>     template<class Alloc> flat_map(const key_container_type&, mapped_container_type&&, const Alloc& a);
>     template<class Alloc> flat_map(key_container_type&&, const mapped_container_type&, const Alloc& a);
>     template<class Alloc> flat_map(key_container_type&&, mapped_container_type&&, const Alloc& a);

This preserves the apparent assumption that `KeyContainer(std::move(kc))` is always efficient but `KeyContainer(std::move(kc), otheralloc)` might not be. Similar wording changes would have to be made to all the `flat_foo` containers.

Tony Table:

>     template<class T, class Comp = std::less<T>, class Container = std::pmr::vector<T>>
>     using pmr_flat_set = std::flat_set<T, Comp, Container>;

>     std::pmr::vector<pmr_flat_set<int>> vs;
>     std::pmr::vector<int> data = {1,2,3};

>     vs.reserve(1);
>     vs.emplace_back(std::move(data));
>       // constructs-in-place with the argument list (std::move(data), get_allocator())
>       // BEFORE: copies (causes heap traffic)
>       // AFTER: moves (no heap traffic)

[2022-11-04; Reflector poll]

Set priority to 2 after reflector poll.

Proposed resolution: