<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3803: flat_foo constructors taking KeyContainer lack KeyCompare parameter</title>
<meta property="og:title" content="Issue 3803: flat_foo constructors taking KeyContainer lack KeyCompare parameter">
<meta property="og:description" content="C++ library issue. Status: C++23">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3803.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++23">C++23</a> status.</em></p>
<h3 id="3803"><a href="lwg-defects.html#3803">3803</a>. <code>flat_<i>foo</i></code> constructors taking <code>KeyContainer</code> lack <code>KeyCompare</code> parameter</h3>
<p><b>Section:</b> 23.6.8 <a href="https://wg21.link/flat.map">[flat.map]</a>, 23.6.9 <a href="https://wg21.link/flat.multimap">[flat.multimap]</a>, 23.6.11 <a href="https://wg21.link/flat.set">[flat.set]</a>, 23.6.12 <a href="https://wg21.link/flat.multiset">[flat.multiset]</a> <b>Status:</b> <a href="lwg-active.html#C++23">C++23</a>
 <b>Submitter:</b> Arthur O'Dwyer <b>Opened:</b> 2022-10-25 <b>Last modified:</b> 2023-11-22</p>
<p><b>Priority: </b>1
</p>
<p><b>View other</b> <a href="lwg-index-open.html#flat.map">active issues</a> in [flat.map].</p>
<p><b>View all other</b> <a href="lwg-index.html#flat.map">issues</a> in [flat.map].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++23">C++23</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<code>flat_set</code>'s current constructor overload set has these two overloads:
</p>
<blockquote><pre>
explicit flat_set(container_type cont);
template&lt;class Allocator&gt;
  flat_set(const container_type&amp; cont, const Allocator&amp; a);
</pre></blockquote>
<p>
I believe it should have these two in addition:
</p>
<blockquote><pre>
flat_set(const key_compare&amp; comp, container_type cont);
template&lt;class Allocator&gt;
  flat_set(const key_compare&amp; comp, const container_type&amp; cont, const Allocator&amp; a);
</pre></blockquote>
<p>
with corresponding deduction guides. Similar wording changes would have to be made to all the 
<code>flat_<i>foo</i></code> containers.
<p/>
Tony Table:
</p>
<blockquote><pre>
struct LessWhenDividedBy {
  int divisor_;
  bool operator()(int x, int y) const { return x/divisor_ &lt; y/divisor_; }
};
std::flat_set&lt;int, LessWhenDividedBy&gt; s(data.begin(), data.end(), LessWhenDividedBy(10));
// BEFORE AND AFTER: okay, but cumbersome
std::flat_set&lt;int, LessWhenDividedBy&gt; s(data);
// BEFORE AND AFTER: oops, this default-constructs the comparator

std::flat_set&lt;int, LessWhenDividedBy&gt; s(LessWhenDividedBy(10), data);
// BEFORE: fails to compile
// AFTER: compiles successfully
</pre></blockquote>

<p><i>[2022-11-04; Reflector poll]</i></p>

<p>
Set priority to 1 after reflector poll.
</p>

<p><i>[2023-02-09 Tim adds wording]</i></p>

<p>
For each construction that takes containers, this wording allow a comparator to be specified as well.
Differing from the suggestion in the issue, the comparator goes last (but before the allocator),
for consistency with every other constructor of <code>flat_<i>meow</i></code> taking a comparator.
(This is inconsistent with <code>priority_queue</code>, but consistency among the type's own
constructors seems more important.)
</p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>

<p><i>[2023-02-13 Approved at February 2023 meeting in Issaquah. Status changed: Immediate &rarr; WP.]</i></p>



<p id="res-3803"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928" title=" Working Draft, Standard for Programming Language C++">N4928</a>.
</p>

<ol>
<li><p>Add a new bullet to 23.6.1 <a href="https://wg21.link/container.adaptors.general">[container.adaptors.general]</a> p6 as indicated:</p>
<blockquote>
<p> -6- A deduction guide for a container adaptor shall not participate in overload 
resolution if any of the following are true:</p>
<ol style="list-style-type:none">
<li>
<p><ins>&mdash; (6.?) It has both <code>KeyContainer</code> and <code>Compare</code>
template parameters, and <code>is_invocable_v&lt;const Compare&amp;, 
const typename KeyContainer::value_type&amp;, 
const typename KeyContainer::value_type&amp;&gt;</code> is not a valid expression
or is <code>false</code>.</ins>
</p>
</li>
</ol>
</blockquote>
</li>
<li><p>Modify 23.6.8.2 <a href="https://wg21.link/flat.map.defn">[flat.map.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class T, class Compare = less&lt;Key&gt;,
           class KeyContainer = vector&lt;Key&gt;, class MappedContainer = vector&lt;T&gt;&gt;
  class flat_map {
  public:
    [&hellip;]
    // 23.6.8.3 <a href="https://wg21.link/flat.map.cons">[flat.map.cons]</a>, construct/copy/destroy
    flat_map() : flat_map(key_compare()) { }

    flat_map(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
             const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
               const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
               const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont<ins>,
             const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_map(sorted_unique_t, const key_container_type&amp; key_cont,
               const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_map(sorted_unique_t, const key_container_type&amp; key_cont,
               const mapped_container_type&amp; mapped_cont, 
               const key_compare&amp; comp, const Allocator&amp; a);</ins>
    [&hellip;]
  };

  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_map(KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_map(KeyContainer, MappedContainer, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_map(KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>


  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_map(sorted_unique_t, KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 23.6.8.3 <a href="https://wg21.link/flat.map.cons">[flat.map.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_map(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
         const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <code>c.keys</code> with <code>std::move(key_cont)</code><ins>,</ins>
<del>and</del> <code>c.values</code> with <code>std::move(mapped_cont)</code><ins>, and <code>compare</code> with <code>comp</code></ins>
<del>; value-initializes <code>compare</code></del>; sorts the range <code>[begin(), end())</code>
with respect to <code>value_comp()</code>; and finally erases the duplicate elements as if by:
</p>
<blockquote>
<pre>
auto zv = ranges::zip_view(c.keys, c.values);
auto it = ranges::unique(zv, key_equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
</pre>
</blockquote>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if the container arguments are already 
sorted with respect to <code>value_comp()</code> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <code>key_cont.size()</code> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
           const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
           const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <code>uses_allocator_v&lt;key_container_type, Allocator&gt;</code> is <code>true</code>
and <code>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-4- <i>Effects:</i> Equivalent to <code>flat_map(key_cont, mapped_cont)</code>
<ins>and <code>flat_map(key_cont, mapped_cont, comp)</code>, respectively</ins>, 
except that <code>c.keys</code> and <code>c.values</code> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <code>flat_map(key_cont, mapped_cont)</code>
<ins>and <code>flat_map(key_cont, mapped_cont, comp)</code>, respectively</ins>.
</p>
</blockquote>

<pre>
flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont<ins>,
         const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Initializes <code>c.keys</code> with <code>std::move(key_cont)</code><ins>,</ins>
<del>and</del> <code>c.values</code> with <code>std::move(mapped_cont)</code><ins>, and <code>compare</code> with <code>comp</code></ins>
<del>; value-initializes <code>compare</code></del>.
<p/>
-7- <i>Complexity:</i> Constant.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_map(sorted_unique_t s, const key_container_type&amp; key_cont,
           const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_map(sorted_unique_t s, const key_container_type&amp; key_cont, 
           const mapped_container_type&amp; mapped_cont, const key_compare&amp; comp,
           const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-8- <i>Constraints:</i> <code>uses_allocator_v&lt;key_container_type, Allocator&gt;</code> is <code>true</code>
and <code>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-9- <i>Effects:</i> Equivalent to <code>flat_map(s, key_cont, mapped_cont)</code>
<ins>and <code>flat_map(s, key_cont, mapped_cont, comp)</code>, respectively</ins>, 
except that <code>c.keys</code> and <code>c.values</code> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-10- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 23.6.9.2 <a href="https://wg21.link/flat.multimap.defn">[flat.multimap.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class T, class Compare = less&lt;Key&gt;,
           class KeyContainer = vector&lt;Key&gt;, class MappedContainer = vector&lt;T&gt;&gt;
  class flat_multimap {
  public:
    [&hellip;]
    // 23.6.9.3 <a href="https://wg21.link/flat.multimap.cons">[flat.multimap.cons]</a>, construct/copy/destroy
    flat_multimap() : flat_multimap(key_compare()) { }

    flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
                  const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                    const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                    const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_multimap(sorted_equivalent_t, 
                  key_container_type key_cont, mapped_container_type mapped_cont<ins>,
                  const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_multimap(sorted_equivalent_t, const key_container_type&amp; key_cont,
                    const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multimap(sorted_equivalent_t, const key_container_type&amp; key_cont,
                    const mapped_container_type&amp; mapped_cont, 
                    const key_compare&amp; comp, const Allocator&amp; a);</ins>
    [&hellip;]
  };

  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_multimap(KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_multimap(KeyContainer, MappedContainer, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_multimap(KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>


  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 23.6.9.3 <a href="https://wg21.link/flat.multimap.cons">[flat.multimap.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
              const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <code>c.keys</code> with <code>std::move(key_cont)</code><ins>,</ins>
<del>and</del> <code>c.values</code> with <code>std::move(mapped_cont)</code><ins>, and <code>compare</code> with <code>comp</code></ins>
<del>; value-initializes <code>compare</code></del>; and sorts the range <code>[begin(), end())</code>
with respect to <code>value_comp()</code>.
</p>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if the container arguments are already 
sorted with respect to <code>value_comp()</code> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <code>key_cont.size()</code> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <code>uses_allocator_v&lt;key_container_type, Allocator&gt;</code> is <code>true</code>
and <code>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-4- <i>Effects:</i> Equivalent to <code>flat_multimap(key_cont, mapped_cont)</code>
<ins>and <code>flat_multimap(key_cont, mapped_cont, comp)</code>, respectively</ins>, 
except that <code>c.keys</code> and <code>c.values</code> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <code>flat_multimap(key_cont, mapped_cont)</code>
<ins>and <code>flat_multimap(key_cont, mapped_cont, comp)</code>, respectively</ins>.
</p>
</blockquote>

<pre>
flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont<ins>,
              const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Initializes <code>c.keys</code> with <code>std::move(key_cont)</code><ins>,</ins>
<del>and</del> <code>c.values</code> with <code>std::move(mapped_cont)</code><ins>, and <code>compare</code> with <code>comp</code></ins>
<del>; value-initializes <code>compare</code></del>.
<p/>
-7- <i>Complexity:</i> Constant.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_multimap(sorted_equivalent_t s, const key_container_type&amp; key_cont,
               const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multimap(sorted_equivalent_t s, const key_container_type&amp; key_cont, 
                const mapped_container_type&amp; mapped_cont, const key_compare&amp; comp,
                const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-8- <i>Constraints:</i> <code>uses_allocator_v&lt;key_container_type, Allocator&gt;</code> is <code>true</code>
and <code>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-9- <i>Effects:</i> Equivalent to <code>flat_multimap(s, key_cont, mapped_cont)</code>
<ins>and <code>flat_multimap(s, key_cont, mapped_cont, comp)</code>, respectively</ins>, 
except that <code>c.keys</code> and <code>c.values</code> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-10- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 23.6.11.2 <a href="https://wg21.link/flat.set.defn">[flat.set.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class Compare = less&lt;Key&gt;, class KeyContainer = vector&lt;Key&gt;&gt;
  class flat_set {
  public:
    [&hellip;]

    // [flat.set.cons], constructors
    flat_set() : flat_set(key_compare()) { }

    explicit flat_set(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_set(const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_set(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_set(sorted_unique_t, container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>)
      : <i>c</i>(std::move(cont)), <i>compare</i>(<ins>comp</ins><del>key_compare()</del>) { }
    template&lt;class Allocator&gt;
      flat_set(sorted_unique_t, const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_set(sorted_unique_t, const container_type&amp; cont, 
               const key_compare&amp; comp, const Allocator&amp; a);</ins>

    [&hellip;]
  };

<ins>
  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_set(KeyContainer, Compare = Compare())
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_set(KeyContainer, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_set(KeyContainer, Compare, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;

  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_set(sorted_unique_t, KeyContainer, Compare = Compare())
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_set(sorted_unique_t, KeyContainer, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_set(sorted_unique_t, KeyContainer, Compare, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 23.6.11.3 <a href="https://wg21.link/flat.set.cons">[flat.set.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_set(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <code><i>c</i></code> with <code>std::move(cont)</code>
<ins> and <code><i>compare</i></code> with <code>comp</code></ins>
<del>, value-initializes <code><i>compare</i></code></del>, sorts the range <code>[begin(), end())</code>
with respect to <code><i>compare</i></code>, and finally erases all but the first element from each group 
of consecutive equivalent elements.
</p>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if <code>cont</code> is already 
sorted with respect to <code><i>compare</i></code> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <code>cont.size()</code> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_set(const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_set(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <code>uses_allocator_v&lt;container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-4- <i>Effects:</i> Equivalent to <code>flat_set(cont)</code>
<ins>and <code>flat_set(cont, comp)</code>, respectively</ins>, 
except that <code><i>c</i></code> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <code>flat_set(cont)</code>
<ins>and <code>flat_set(cont, comp)</code>, respectively</ins>.
</p>
</blockquote>

<pre>
template&lt;class Allocator&gt;
  flat_set(sorted_unique_t s, const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_set(sorted_unique_t s, const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-6- <i>Constraints:</i> <code>uses_allocator_v&lt;container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-7- <i>Effects:</i> Equivalent to <code>flat_set(s, cont)</code>
<ins>and <code>flat_set(s, cont, comp)</code>, respectively</ins>, 
except that <code><i>c</i></code> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-8- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>
<li><p>Modify 23.6.12.2 <a href="https://wg21.link/flat.multiset.defn">[flat.multiset.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class Compare = less&lt;Key&gt;, class KeyContainer = vector&lt;Key&gt;&gt;
  class flat_multiset {
  public:
    [&hellip;]

    // [flat.multiset.cons], constructors
    flat_multiset() : flat_multiset(key_compare()) { }

    explicit flat_multiset(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_multiset(const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multiset(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_multiset(sorted_equivalent_t, container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>)
      : <i>c</i>(std::move(cont)), <i>compare</i>(<ins>comp</ins><del>key_compare()</del>) { }
    template&lt;class Allocator&gt;
      flat_multiset(sorted_equivalent_t, const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multiset(sorted_equivalent_t, const container_type&amp; cont, 
                    const key_compare&amp; comp, const Allocator&amp; a);</ins>

    [&hellip;]
  };

<ins>
  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_multiset(KeyContainer, Compare = Compare())
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_multiset(KeyContainer, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_multiset(KeyContainer, Compare, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;

  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare())
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_multiset(sorted_equivalent_t, KeyContainer, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 23.6.12.3 <a href="https://wg21.link/flat.multiset.cons">[flat.multiset.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_multiset(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <code><i>c</i></code> with <code>std::move(cont)</code>
<ins> and <code><i>compare</i></code> with <code>comp</code></ins>
<del>, value-initializes <code><i>compare</i></code></del>, and sorts the range <code>[begin(), end())</code>
with respect to <code><i>compare</i></code>.
</p>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if <code>cont</code> is already 
sorted with respect to <code><i>compare</i></code> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <code>cont.size()</code> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_multiset(const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multiset(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <code>uses_allocator_v&lt;container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-4- <i>Effects:</i> Equivalent to <code>flat_multiset(cont)</code>
<ins>and <code>flat_multiset(cont, comp)</code>, respectively</ins>, 
except that <code><i>c</i></code> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <code>flat_multiset(cont)</code>
<ins>and <code>flat_multiset(cont, comp)</code>, respectively</ins>.
</p>
</blockquote>

<pre>
template&lt;class Allocator&gt;
  flat_multiset(sorted_equivalent_t s, const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multiset(sorted_equivalent_t s, const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-6- <i>Constraints:</i> <code>uses_allocator_v&lt;container_type, Allocator&gt;</code> is <code>true</code>.
<p/>
-7- <i>Effects:</i> Equivalent to <code>flat_multiset(s, cont)</code>
<ins>and <code>flat_multiset(s, cont, comp)</code>, respectively</ins>, 
except that <code><i>c</i></code> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-8- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
