Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2226153/?format=api
{ "id": 2226153, "url": "http://patchwork.ozlabs.org/api/patches/2226153/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhuay3vzv6.gcc.gcc-TEST.ppalka.9.1.3@forge-stage.sourceware.org/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<bmm.hhuay3vzv6.gcc.gcc-TEST.ppalka.9.1.3@forge-stage.sourceware.org>", "list_archive_url": null, "date": "2026-04-22T10:14:44", "name": "[v1,3/3] libstdc++: Implement C++23 <flat_set> (P1222R4)", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "8ff5a1ba74565a00bc36dc5bf3edbd252784d8db", "submitter": { "id": 93215, "url": "http://patchwork.ozlabs.org/api/people/93215/?format=api", "name": "ppalka via Sourceware Forge", "email": "forge-bot+ppalka@forge-stage.sourceware.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/bmm.hhuay3vzv6.gcc.gcc-TEST.ppalka.9.1.3@forge-stage.sourceware.org/mbox/", "series": [ { "id": 500959, "url": "http://patchwork.ozlabs.org/api/series/500959/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=500959", "date": "2026-04-22T10:14:41", "name": "libstdc++: Implement C++23 <flat_map> and <flat_set>", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/500959/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2226153/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2226153/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org; dmarc=none (p=none dis=none)\n header.from=forge-stage.sourceware.org", "sourceware.org;\n spf=pass smtp.mailfrom=forge-stage.sourceware.org", "server2.sourceware.org;\n arc=none smtp.remote-ip=38.145.34.39" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g0w9w62zGz1y2d\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 20:16:36 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id F10F84B9DB64\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 22 Apr 2026 10:16:34 +0000 (GMT)", "from forge-stage.sourceware.org (vm08.sourceware.org [38.145.34.39])\n by sourceware.org (Postfix) with ESMTPS id B04A54BA9011\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 10:15:59 +0000 (GMT)", "from forge-stage.sourceware.org (localhost [IPv6:::1])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256)\n (No client certificate requested)\n by forge-stage.sourceware.org (Postfix) with ESMTPS id 7B26840556\n for <gcc-patches@gcc.gnu.org>; Wed, 22 Apr 2026 10:15:59 +0000 (UTC)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org F10F84B9DB64", "OpenDKIM Filter v2.11.0 sourceware.org B04A54BA9011" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org B04A54BA9011", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org B04A54BA9011", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776852959; cv=none;\n b=NxlN1dIWp5zHE3JjGEKFa7KKYEObpyoz3mwWmOIS1fEudOvxIkCGyIfv015m8uLAdj/UnyC6AcQnNXoVnWVb9MiWTCsJMrz7VXBLVKYBsyioDlHEp0hPjRImNtt+XvRKzRpJ2FAt3MQyD9WrJ4JCwxAU6EVUP3K7z31KcTODCxk=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776852959; c=relaxed/simple;\n bh=42QprnOOXOuZzMtU33J/UeuqrS9cclTaJfQ3KOfzQ2o=;\n h=From:Date:Subject:To:Message-ID;\n b=WeqRbSR5DZIzferXNdafzf9bxsC0EFpjdGF69inXPhO+Wr0AINKi/f4tRWo+20SwaznLLZsZtbVJd/SRSgczIDee3fongRkwrKC08cvQYBC4ZeR7QYk3uIn1xS2wR/+GqcgYHmY8VDVlrjlDYNVBdNSMOmK0+h2Tieixz0cVJ9Y=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "From": "ppalka via Sourceware Forge\n <forge-bot+ppalka@forge-stage.sourceware.org>", "Date": "Wed, 22 Apr 2026 10:14:44 +0000", "Subject": "[PATCH v1 3/3] libstdc++: Implement C++23 <flat_set> (P1222R4)", "To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>", "Message-ID": "\n <bmm.hhuay3vzv6.gcc.gcc-TEST.ppalka.9.1.3@forge-stage.sourceware.org>", "X-Mailer": "batrachomyomachia", "X-Requested-Reviewer": "redi", "X-Pull-Request-Organization": "gcc", "X-Pull-Request-Repository": "gcc-TEST", "X-Pull-Request": "https://forge.sourceware.org/gcc/gcc-TEST/pulls/9", "References": "\n <bmm.hhuay3vzv6.gcc.gcc-TEST.ppalka.9.1.0@forge-stage.sourceware.org>", "In-Reply-To": "\n <bmm.hhuay3vzv6.gcc.gcc-TEST.ppalka.9.1.0@forge-stage.sourceware.org>", "X-Patch-URL": "\n https://forge.sourceware.org/gcc/gcc-TEST/commit/b564cb690469527d0825f7303ac8275ed19206d0", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Reply-To": "gcc-patches mailing list <gcc-patches@gcc.gnu.org>,\n ppalka@gcc.gnu.org", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "From: Patrick Palka <ppalka@redhat.com>\n\nThis implements the C++23 container adaptors std::flat_set and\nstd::flat_multiset from P1222R4. The implementation is essentially\nan simpler and pared down version of std::flat_map.\n\nlibstdc++-v3/ChangeLog:\n\n\t* include/Makefile.am: Add new header <flat_set>.\n\t* include/Makefile.in: Regenerate.\n\t* include/bits/version.def (__cpp_flat_set): Define.\n\t* include/bits/version.h: Regenerate\n\t* include/std/flat_set: New file.\n\t* testsuite/23_containers/flat_multiset/1.cc: New test.\n\t* testsuite/23_containers/flat_set/1.cc: New test.\n---\n libstdc++-v3/include/Makefile.am | 1 +\n libstdc++-v3/include/Makefile.in | 1 +\n libstdc++-v3/include/bits/version.def | 8 +\n libstdc++-v3/include/bits/version.h | 10 +\n libstdc++-v3/include/precompiled/stdc++.h | 1 +\n libstdc++-v3/include/std/flat_set | 1040 +++++++++++++++++\n libstdc++-v3/src/c++23/std.cc.in | 10 +\n .../23_containers/flat_multiset/1.cc | 131 +++\n .../testsuite/23_containers/flat_set/1.cc | 146 +++\n 9 files changed, 1348 insertions(+)\n create mode 100644 libstdc++-v3/include/std/flat_set\n create mode 100644 libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/flat_set/1.cc", "diff": "diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am\nindex b606bcd49359..3e1e42e79737 100644\n--- a/libstdc++-v3/include/Makefile.am\n+++ b/libstdc++-v3/include/Makefile.am\n@@ -71,6 +71,7 @@ std_headers = \\\n \t${std_srcdir}/execution \\\n \t${std_srcdir}/filesystem \\\n \t${std_srcdir}/flat_map \\\n+\t${std_srcdir}/flat_set \\\n \t${std_srcdir}/format \\\n \t${std_srcdir}/forward_list \\\n \t${std_srcdir}/fstream \\\ndiff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in\nindex d277f87905b9..4c461afb7513 100644\n--- a/libstdc++-v3/include/Makefile.in\n+++ b/libstdc++-v3/include/Makefile.in\n@@ -427,6 +427,7 @@ std_freestanding = \\\n @GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/execution \\\n @GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/filesystem \\\n @GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/flat_map \\\n+@GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/flat_set \\\n @GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/format \\\n @GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/forward_list \\\n @GLIBCXX_HOSTED_TRUE@\t${std_srcdir}/fstream \\\ndiff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def\nindex 171ee2780e8d..3b31cff51943 100644\n--- a/libstdc++-v3/include/bits/version.def\n+++ b/libstdc++-v3/include/bits/version.def\n@@ -1671,6 +1671,14 @@ ftms = {\n };\n };\n \n+ftms = {\n+ name = flat_set;\n+ values = {\n+ v = 202207;\n+ cxxmin = 23;\n+ };\n+};\n+\n ftms = {\n name = formatters;\n values = {\ndiff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h\nindex 5e1858855eb6..ef27ae5e4fae 100644\n--- a/libstdc++-v3/include/bits/version.h\n+++ b/libstdc++-v3/include/bits/version.h\n@@ -1845,6 +1845,16 @@\n #endif /* !defined(__cpp_lib_flat_map) && defined(__glibcxx_want_flat_map) */\n #undef __glibcxx_want_flat_map\n \n+#if !defined(__cpp_lib_flat_set)\n+# if (__cplusplus >= 202100L)\n+# define __glibcxx_flat_set 202207L\n+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_flat_set)\n+# define __cpp_lib_flat_set 202207L\n+# endif\n+# endif\n+#endif /* !defined(__cpp_lib_flat_set) && defined(__glibcxx_want_flat_set) */\n+#undef __glibcxx_want_flat_set\n+\n #if !defined(__cpp_lib_formatters)\n # if (__cplusplus >= 202100L) && _GLIBCXX_HOSTED\n # define __glibcxx_formatters 202302L\ndiff --git a/libstdc++-v3/include/precompiled/stdc++.h b/libstdc++-v3/include/precompiled/stdc++.h\nindex 67ee00d073bb..3312a7a4dd4d 100644\n--- a/libstdc++-v3/include/precompiled/stdc++.h\n+++ b/libstdc++-v3/include/precompiled/stdc++.h\n@@ -226,6 +226,7 @@\n #if __cplusplus > 202002L\n #include <expected>\n #include <flat_map>\n+#include <flat_set>\n #include <generator>\n #include <print>\n #include <spanstream>\ndiff --git a/libstdc++-v3/include/std/flat_set b/libstdc++-v3/include/std/flat_set\nnew file mode 100644\nindex 000000000000..60205b64c933\n--- /dev/null\n+++ b/libstdc++-v3/include/std/flat_set\n@@ -0,0 +1,1040 @@\n+// <flat_set> -*- C++ -*-\n+\n+// Copyright The GNU Toolchain Authors.\n+//\n+// This file is part of the GNU ISO C++ Library. This library is free\n+// software; you can redistribute it and/or modify it under the\n+// terms of the GNU General Public License as published by the\n+// Free Software Foundation; either version 3, or (at your option)\n+// any later version.\n+\n+// This library is distributed in the hope that it will be useful,\n+// but WITHOUT ANY WARRANTY; without even the implied warranty of\n+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n+// GNU General Public License for more details.\n+\n+// Under Section 7 of GPL version 3, you are granted additional\n+// permissions described in the GCC Runtime Library Exception, version\n+// 3.1, as published by the Free Software Foundation.\n+\n+// You should have received a copy of the GNU General Public License and\n+// a copy of the GCC Runtime Library Exception along with this program;\n+// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see\n+// <http://www.gnu.org/licenses/>.\n+\n+/** @file include/flat_set\n+ * This is a Standard C++ Library header.\n+ */\n+\n+#ifndef _GLIBCXX_FLAT_SET\n+#define _GLIBCXX_FLAT_SET 1\n+\n+#ifdef _GLIBCXX_SYSHDR\n+#pragma GCC system_header\n+#endif\n+\n+#define __glibcxx_want_flat_set\n+#include <bits/version.h>\n+\n+#ifdef __cpp_lib_flat_set // >= C++23\n+\n+#include <compare>\n+#include <initializer_list>\n+\n+#include <exception>\n+#include <functional> // not_fn\n+#include <optional>\n+#include <type_traits>\n+#include <vector>\n+#include <bits/functexcept.h>\n+#include <bits/stl_algo.h>\n+#include <bits/stl_function.h> // less\n+#include <bits/stl_pair.h>\n+#include <bits/uses_allocator_args.h> // make_obj_using_allocator\n+#ifdef _GLIBCXX_DEBUG\n+# include <bits/ranges_algo.h> // ranges::is_sorted\n+#endif\n+\n+namespace std _GLIBCXX_VISIBILITY(default)\n+{\n+_GLIBCXX_BEGIN_NAMESPACE_VERSION\n+\n+ template<typename _Key, typename _Compare,\n+\t typename _KeyContainer>\n+ class flat_set;\n+\n+ template<typename _Key, typename _Compare,\n+\t typename _KeyContainer>\n+ class flat_multiset;\n+\n+ template<typename _Key, typename _Compare, typename _KeyContainer, bool _Multi>\n+ class _Flat_set_impl\n+ {\n+ static_assert(is_same_v<_Key, typename _KeyContainer::value_type>);\n+ static_assert(is_nothrow_swappable_v<_KeyContainer>);\n+\n+ using _Derived = __conditional_t<_Multi,\n+\t\t\t\t flat_multiset<_Key, _Compare, _KeyContainer>,\n+\t\t\t\t flat_set<_Key, _Compare, _KeyContainer>>;\n+ using __sorted_t = __conditional_t<_Multi, sorted_equivalent_t, sorted_unique_t>;\n+\n+ public:\n+ using key_type = _Key;\n+ using value_type = _Key;\n+ using key_compare = _Compare;\n+ using value_compare = _Compare;\n+ using reference = value_type&;\n+ using const_reference = const value_type&;\n+ using size_type = typename _KeyContainer::size_type;\n+ using difference_type = typename _KeyContainer::difference_type;\n+ using iterator = typename _KeyContainer::const_iterator;\n+ using const_iterator = typename _KeyContainer::const_iterator;\n+ using reverse_iterator = std::reverse_iterator<iterator>;\n+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;\n+ using container_type = _KeyContainer;\n+\n+ private:\n+ using __emplace_result_t = __conditional_t<_Multi, iterator, pair<iterator, bool>>;\n+\n+ struct _ClearGuard\n+ {\n+\tcontainer_type* _M_cont;\n+\n+\t_ClearGuard(container_type& __cont)\n+\t: _M_cont(std::__addressof(__cont))\n+\t{ }\n+\n+\t~_ClearGuard()\n+\t{\n+\t if (_M_cont)\n+\t _M_cont->clear();\n+\t}\n+\n+\tvoid\n+\t_M_disable()\n+\t{ _M_cont = nullptr; }\n+ };\n+\n+ _ClearGuard\n+ _M_make_clear_guard()\n+ { return _ClearGuard{this->_M_cont}; }\n+\n+ public:\n+ // constructors\n+ _Flat_set_impl() : _Flat_set_impl(key_compare()) { }\n+\n+ explicit\n+ _Flat_set_impl(const key_compare& __comp)\n+ : _M_cont(), _M_comp(__comp)\n+ { }\n+\n+ _Flat_set_impl(container_type __cont, const key_compare& __comp = key_compare())\n+ : _M_cont(std::move(__cont)), _M_comp(__comp)\n+ { _M_sort_uniq(); }\n+\n+ _Flat_set_impl(__sorted_t,\n+\t\t container_type __cont, const key_compare& __comp = key_compare())\n+ : _M_cont(std::move(__cont)), _M_comp(__comp)\n+ { _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); }\n+\n+ template<__has_input_iter_cat _InputIterator>\n+\t_Flat_set_impl(_InputIterator __first, _InputIterator __last,\n+\t\t const key_compare& __comp = key_compare())\n+\t: _M_cont(), _M_comp(__comp)\n+\t{ insert(__first, __last); }\n+\n+ template<__has_input_iter_cat _InputIterator>\n+\t_Flat_set_impl(__sorted_t __s,\n+\t\t _InputIterator __first, _InputIterator __last,\n+\t\t const key_compare& __comp = key_compare())\n+\t: _M_cont(), _M_comp(__comp)\n+\t{ insert(__s, __first, __last); }\n+\n+ template<__detail::__container_compatible_range<value_type> _Rg>\n+\t_Flat_set_impl(from_range_t __fr, _Rg&& __rg)\n+\t: _Flat_set_impl(__fr, std::forward<_Rg>(__rg), key_compare())\n+\t{ }\n+\n+ template<__detail::__container_compatible_range<value_type> _Rg>\n+\t_Flat_set_impl(from_range_t, _Rg&& __rg, const key_compare& __comp)\n+\t: _Flat_set_impl(__comp)\n+\t{ insert_range(std::forward<_Rg>(__rg)); }\n+\n+ _Flat_set_impl(initializer_list<value_type> __il,\n+\t\t const key_compare& __comp = key_compare())\n+ : _Flat_set_impl(__il.begin(), __il.end(), __comp)\n+ { }\n+\n+ _Flat_set_impl(__sorted_t __s,\n+\t\t initializer_list<value_type> __il,\n+\t\t const key_compare& __comp = key_compare())\n+ : _Flat_set_impl(__s, __il.begin(), __il.end(), __comp)\n+ { }\n+\n+ // constructors with allocators\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\texplicit\n+\t_Flat_set_impl(const _Alloc& __a)\n+\t: _Flat_set_impl(key_compare(), __a)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(const key_compare& __comp, const _Alloc& __a)\n+\t: _M_cont(std::make_obj_using_allocator<container_type>(__a)),\n+\t _M_comp(__comp)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(const container_type& __cont, const _Alloc& __a)\n+\t: _Flat_set_impl(__cont, key_compare(), __a)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(const container_type& __cont, const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _M_cont(std::make_obj_using_allocator<container_type>(__a, __cont)),\n+\t _M_comp(__comp)\n+\t{ _M_sort_uniq(); }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(__sorted_t __s, const container_type& __cont, const _Alloc& __a)\n+\t: _Flat_set_impl(__s, __cont, key_compare(), __a)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(__sorted_t, const container_type& __cont, const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _M_cont(std::make_obj_using_allocator<container_type>(__a, __cont)),\n+\t _M_comp(__comp)\n+\t{ _GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(_M_cont, _M_comp)); }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(const _Derived& __x, const _Alloc& __a)\n+\t: _M_cont(std::make_obj_using_allocator<container_type>(__a, __x._M_cont)),\n+\t _M_comp(__x._M_comp)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(_Derived&& __x, const _Alloc& __a)\n+\t: _M_cont(std::make_obj_using_allocator<container_type>(__a, std::move(__x._M_cont))),\n+\t _M_comp(__x._M_comp)\n+\t{ }\n+\n+ template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(_InputIterator __first, _InputIterator __last,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(std::move(__first), std::move(__last), key_compare(), __a)\n+\t{ }\n+\n+ template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(_InputIterator __first, _InputIterator __last,\n+\t\t const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__comp, __a)\n+\t{ insert(__first, __last); }\n+\n+ template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(__sorted_t __s,\n+\t\t _InputIterator __first, _InputIterator __last,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__s, std::move(__first), std::move(__last), key_compare(), __a)\n+\t{ }\n+\n+ template<__has_input_iter_cat _InputIterator, __allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(__sorted_t __s,\n+\t\t _InputIterator __first, _InputIterator __last,\n+\t\t const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__comp, __a)\n+\t{ insert(__s, __first, __last); }\n+\n+ template<__detail::__container_compatible_range<value_type> _Rg,\n+\t __allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(from_range_t __fr, _Rg&& __rg,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__fr, std::forward<_Rg>(__rg), key_compare(), __a)\n+\t{ }\n+\n+ template<__detail::__container_compatible_range<value_type> _Rg,\n+\t __allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(from_range_t, _Rg&& __rg,\n+\t\t const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__comp, __a)\n+\t{ insert_range(std::forward<_Rg>(__rg)); }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(initializer_list<value_type> __il,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__il, key_compare(), __a)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(initializer_list<value_type> __il,\n+\t\t const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__il.begin(), __il.end(), __comp, __a)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(__sorted_t __s,\n+\t\t initializer_list<value_type> __il,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__s, __il.begin(), __il.end(), key_compare(), __a)\n+\t{ }\n+\n+ template<__allocator_for<container_type> _Alloc>\n+\t_Flat_set_impl(__sorted_t __s,\n+\t\t initializer_list<value_type> __il,\n+\t\t const key_compare& __comp,\n+\t\t const _Alloc& __a)\n+\t: _Flat_set_impl(__s, __il.begin(), __il.end(), __comp, __a)\n+\t{ }\n+\n+ _Derived&\n+ operator=(initializer_list<value_type> __il)\n+ {\n+\tauto __guard = _M_make_clear_guard();\n+\t_M_cont = __il;\n+\t_M_sort_uniq();\n+\t__guard._M_disable();\n+\treturn static_cast<_Derived&>(*this);\n+ }\n+\n+ // iterators\n+ const_iterator\n+ begin() const noexcept\n+ { return _M_cont.begin(); }\n+\n+ const_iterator\n+ end() const noexcept\n+ { return _M_cont.end(); }\n+\n+ const_reverse_iterator\n+ rbegin() const noexcept\n+ { return const_reverse_iterator(end()); }\n+\n+ const_reverse_iterator\n+ rend() const noexcept\n+ { return const_reverse_iterator(begin()); }\n+\n+ const_iterator\n+ cbegin() const noexcept\n+ { return begin(); }\n+\n+ const_iterator\n+ cend() const noexcept\n+ { return end(); }\n+\n+ const_reverse_iterator\n+ crbegin() const noexcept\n+ { return rbegin(); }\n+\n+ const_reverse_iterator\n+ crend() const noexcept\n+ { return rend(); }\n+\n+ // capacity\n+ [[nodiscard]] bool\n+ empty() const noexcept\n+ { return _M_cont.empty(); }\n+\n+ size_type\n+ size() const noexcept\n+ { return _M_cont.size(); }\n+\n+ size_type\n+ max_size() const noexcept\n+ { return _M_cont.max_size(); }\n+\n+ // modifiers\n+ template<typename... _Args>\n+\tpair<iterator, bool>\n+\t_M_try_emplace(optional<const_iterator> __hint, _Args&&... __args)\n+\t{\n+\t // TODO: Simplify and audit the hint handling.\n+\t value_type __k(std::forward<_Args>(__args)...);\n+\t typename container_type::iterator __it;\n+\t int __r = -1, __s = -1;\n+\t if (__hint.has_value()\n+\t && (__hint == cbegin()\n+\t\t || (__r = !_M_comp(__k, (*__hint)[-1]))) // k >= hint[-1]\n+\t && (__hint == cend()\n+\t\t || (__s = !_M_comp((*__hint)[0], __k)))) // k <= hint[0]\n+\t {\n+\t __it = _M_cont.begin() + (*__hint - begin());\n+\t if constexpr (!_Multi)\n+\t\tif (__r == 1 && !_M_comp(__it[-1], __k)) // k == hint[-1]\n+\t\t return {__it - 1, false};\n+\t }\n+\t else\n+\t {\n+\t auto __first = _M_cont.begin();\n+\t auto __last = _M_cont.end();\n+\t if (__r == 1) // k >= hint[-1]\n+\t\t__first += *__hint - _M_cont.begin();\n+\t else if (__r == 0) // k < __hint[-1]\n+\t\t__last = __first + (*__hint - _M_cont.begin());\n+\t if constexpr (_Multi)\n+\t\t{\n+\t\t if (__s == 0) // hint[0] < k\n+\t\t // Insert before the leftmost equivalent key.\n+\t\t __it = std::lower_bound(__first, __last, __k, _M_comp);\n+\t\t else\n+\t\t // Insert after the rightmost equivalent key.\n+\t\t __it = std::upper_bound(std::make_reverse_iterator(__last),\n+\t\t\t\t\t std::make_reverse_iterator(__first),\n+\t\t\t\t\t __k, std::not_fn(_M_comp)).base();\n+\t\t}\n+\t else\n+\t\t__it = std::lower_bound(__first, __last, __k, _M_comp);\n+\t }\n+\n+\t if constexpr (!_Multi)\n+\t if (__it != _M_cont.end() && !_M_comp(__k, __it[0]))\n+\t return {__it, false};\n+\n+\t auto __guard = _M_make_clear_guard();\n+\t __it = _M_cont.insert(__it, std::move(__k));\n+\t __guard._M_disable();\n+\t return {__it, true};\n+\t}\n+\n+ template<typename... _Args>\n+\trequires is_constructible_v<value_type, _Args...>\n+\t__emplace_result_t\n+\templace(_Args&&... __args)\n+\t{\n+\t auto __r = _M_try_emplace(nullopt, std::forward<_Args>(__args)...);\n+\t if constexpr (_Multi)\n+\t return __r.first;\n+\t else\n+\t return __r;\n+\t}\n+\n+ template<typename... _Args>\n+\titerator\n+\templace_hint(const_iterator __position, _Args&&... __args)\n+\t{ return _M_try_emplace(__position, std::forward<_Args>(__args)...).first; }\n+\n+ __emplace_result_t\n+ insert(const value_type& __x)\n+ { return emplace(__x); }\n+\n+ __emplace_result_t\n+ insert(value_type&& __x)\n+ { return emplace(std::move(__x)); }\n+\n+ iterator\n+ insert(const_iterator __position, const value_type& __x)\n+ { return emplace_hint(__position, __x); }\n+\n+ iterator\n+ insert(const_iterator __position, value_type&& __x)\n+ { return emplace_hint(__position, std::move(__x)); }\n+\n+ template<typename _Arg>\n+\trequires is_constructible_v<value_type, _Arg>\n+\t__emplace_result_t\n+\tinsert(_Arg&& __x)\n+\t{ return emplace(std::forward<_Arg>(__x)); }\n+\n+ template<typename _Arg>\n+\trequires is_constructible_v<value_type, _Arg>\n+\titerator\n+\tinsert(const_iterator __position, _Arg&& __x)\n+\t{ return emplace_hint(__position, std::forward<_Arg>(__x)); }\n+\n+ template<__has_input_iter_cat _InputIterator>\n+\tvoid\n+\tinsert(_InputIterator __first, _InputIterator __last)\n+\t{\n+\t auto __guard = _M_make_clear_guard();\n+\t auto __it = _M_cont.insert(_M_cont.end(), __first, __last);\n+\t std::sort(__it, _M_cont.end(), _M_comp);\n+\t std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp);\n+\t if constexpr (!_Multi)\n+\t _M_unique();\n+\t __guard._M_disable();\n+\t}\n+\n+ template<__has_input_iter_cat _InputIterator>\n+\tvoid\n+\tinsert(__sorted_t, _InputIterator __first, _InputIterator __last)\n+\t{\n+\t auto __guard = _M_make_clear_guard();\n+\t auto __it = _M_cont.insert(_M_cont.end(), __first, __last);\n+\t std::inplace_merge(_M_cont.begin(), __it, _M_cont.end(), _M_comp);\n+\t if constexpr (!_Multi)\n+\t _M_unique();\n+\t __guard._M_disable();\n+\t}\n+\n+ template<__detail::__container_compatible_range<value_type> _Rg>\n+\tvoid\n+\tinsert_range(_Rg&& __rg)\n+\t{ insert(ranges::begin(__rg), ranges::end(__rg)); }\n+\n+ void\n+ insert(initializer_list<value_type> __il)\n+ { insert(__il.begin(), __il.end()); }\n+\n+ void\n+ insert(__sorted_t __s, initializer_list<value_type> __il)\n+ { insert(__s, __il.begin(), __il.end()); }\n+\n+ container_type\n+ extract() &&\n+ {\n+\tauto __guard = _M_make_clear_guard();\n+\treturn std::move(_M_cont);\n+ }\n+\n+ void\n+ replace(container_type&& __cont)\n+ {\n+\t_GLIBCXX_DEBUG_ASSERT(ranges::is_sorted(__cont, _M_comp));\n+\tauto __guard = _M_make_clear_guard();\n+\t_M_cont = std::move(__cont);\n+\t__guard._M_disable();\n+ }\n+\n+ iterator\n+ erase(const_iterator __position)\n+ { return _M_cont.erase(__position); }\n+\n+ size_type\n+ erase(const key_type& __x)\n+ { return erase<const key_type&>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<remove_cvref_t<_Key2>, _Key>\n+\t || (__transparent_comparator<_Compare>\n+\t && !is_convertible_v<_Key2, iterator>\n+\t && !is_convertible_v<_Key2, const_iterator>)\n+\tsize_type\n+\terase(_Key2&& __x)\n+\t{\n+\t auto [__first, __last] = equal_range(std::forward<_Key2>(__x));\n+\t auto __n = __last - __first;\n+\t erase(__first, __last);\n+\t return __n;\n+\t}\n+\n+ iterator\n+ erase(const_iterator __first, const_iterator __last)\n+ { return _M_cont.erase(__first, __last); }\n+\n+ void\n+ swap(_Derived& __x) noexcept\n+ {\n+\tusing std::swap;\n+\tswap(_M_cont, __x._M_cont);\n+\tswap(_M_comp, __x._M_comp);\n+ }\n+\n+ void\n+ clear() noexcept\n+ { _M_cont.clear(); }\n+\n+ // observers\n+ [[nodiscard]]\n+ key_compare\n+ key_comp() const\n+ { return _M_comp; }\n+\n+ [[nodiscard]]\n+ value_compare\n+ value_comp() const\n+ { return _M_comp; }\n+\n+ // map operations\n+ [[nodiscard]]\n+ iterator\n+ find(const key_type& __x)\n+ { return find<key_type>(__x); }\n+\n+ [[nodiscard]]\n+ const_iterator\n+ find(const key_type& __x) const\n+ { return find<key_type>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\titerator\n+\tfind(const _Key2& __x)\n+\t{\n+\t auto __it = lower_bound(__x);\n+\t if (__it != end() && !_M_comp(__x, *__it))\n+\t return __it;\n+\t else\n+\t return end();\n+\t}\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tconst_iterator\n+\tfind(const _Key2& __x) const\n+\t{\n+\t auto __it = lower_bound(__x);\n+\t if (__it != cend() && !_M_comp(__x, *__it))\n+\t return __it;\n+\t else\n+\t return cend();\n+\t}\n+\n+ [[nodiscard]]\n+ size_type\n+ count(const key_type& __x) const\n+ { return count<key_type>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tsize_type\n+\tcount(const _Key2& __x) const\n+\t{\n+\t if constexpr (!_Multi)\n+\t return contains<_Key2>(__x);\n+\t else\n+\t {\n+\t auto [__first, __last] = equal_range(__x);\n+\t return __last - __first;\n+\t }\n+\t}\n+\n+ [[nodiscard]]\n+ bool\n+ contains(const key_type& __x) const\n+ { return contains<key_type>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tbool\n+\tcontains(const _Key2& __x) const\n+\t{ return find(__x) != cend(); }\n+\n+ [[nodiscard]]\n+ iterator\n+ lower_bound(const key_type& __x)\n+ { return lower_bound<key_type>(__x); }\n+\n+ [[nodiscard]]\n+ const_iterator\n+ lower_bound(const key_type& __x) const\n+ { return lower_bound<key_type>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\titerator\n+\tlower_bound(const _Key2& __x)\n+\t{ return std::lower_bound(begin(), end(), __x, _M_comp); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tconst_iterator\n+\tlower_bound(const _Key2& __x) const\n+\t{ return std::lower_bound(begin(), end(), __x, _M_comp); }\n+\n+ [[nodiscard]]\n+ iterator\n+ upper_bound(const key_type& __x)\n+ { return upper_bound<key_type>(__x); }\n+\n+ [[nodiscard]]\n+ const_iterator\n+ upper_bound(const key_type& __x) const\n+ { return upper_bound<key_type>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\titerator\n+\tupper_bound(const _Key2& __x)\n+\t{ return std::upper_bound(begin(), end(), __x, _M_comp); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tconst_iterator\n+\tupper_bound(const _Key2& __x) const\n+\t{ return std::upper_bound(begin(), end(), __x, _M_comp); }\n+\n+ [[nodiscard]]\n+ pair<iterator, iterator>\n+ equal_range(const key_type& __x)\n+ { return equal_range<key_type>(__x); }\n+\n+ [[nodiscard]]\n+ pair<const_iterator, const_iterator>\n+ equal_range(const key_type& __x) const\n+ { return equal_range<key_type>(__x); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tpair<iterator, iterator>\n+\tequal_range(const _Key2& __x)\n+\t{ return std::equal_range(begin(), end(), __x, _M_comp); }\n+\n+ template<typename _Key2>\n+\trequires same_as<_Key2, _Key> || __transparent_comparator<_Compare>\n+\t[[nodiscard]]\n+\tpair<const_iterator, const_iterator>\n+\tequal_range(const _Key2& __x) const\n+\t{ return std::equal_range(begin(), end(), __x, _M_comp); }\n+\n+ [[nodiscard]]\n+ friend bool\n+ operator==(const _Derived& __x, const _Derived& __y)\n+ { return std::equal(__x.begin(), __x.end(), __y.begin(), __y.end()); }\n+\n+ template<typename _Up = value_type>\n+\t[[nodiscard]]\n+\tfriend __detail::__synth3way_t<_Up>\n+\toperator<=>(const _Derived& __x, const _Derived& __y)\n+\t{\n+\t return std::lexicographical_compare_three_way(__x.begin(), __x.end(),\n+\t\t\t\t\t\t\t__y.begin(), __y.end(),\n+\t\t\t\t\t\t\t__detail::__synth3way);\n+\t}\n+\n+ friend void\n+ swap(_Derived& __x, _Derived& __y) noexcept\n+ { return __x.swap(__y); }\n+\n+ template<typename _Predicate>\n+\tfriend size_type\n+\terase_if(_Derived& __c, _Predicate __pred)\n+\t{\n+\t auto __guard = __like_t<_Derived&, _Flat_set_impl>(__c)._M_make_clear_guard();\n+\t auto __first = __c._M_cont.begin();\n+\t auto __last = __c._M_cont.end();\n+\t __first = std::remove_if(__first, __last, __pred);\n+\t auto __n = __last - __first;\n+\t __c.erase(__first, __last);\n+\t __guard._M_disable();\n+\t return __n;\n+\t}\n+\n+ private:\n+ container_type _M_cont;\n+ [[no_unique_address]] _Compare _M_comp;\n+\n+ void\n+ _M_sort_uniq()\n+ {\n+\tstd::sort(_M_cont.begin(), _M_cont.end(), _M_comp);\n+\tif constexpr (!_Multi)\n+\t _M_unique();\n+ }\n+\n+ void\n+ _M_unique() requires (!_Multi)\n+ {\n+\tstruct __key_equiv\n+\t{\n+\t __key_equiv(key_compare __c) : _M_comp(__c) { }\n+\n+\t bool\n+\t operator()(const_reference __x, const_reference __y) const\n+\t { return !_M_comp(__x, __y) && !_M_comp(__y, __x); }\n+\n+\t [[no_unique_address]] key_compare _M_comp;\n+\t};\n+\n+\tauto __first = _M_cont.begin();\n+\tauto __last = _M_cont.end();\n+\t__first = std::unique(__first, __last, __key_equiv(_M_comp));\n+\t_M_cont.erase(__first, __last);\n+ }\n+ };\n+\n+ /* Class template flat_set - container adaptor\n+ *\n+ * @ingroup\n+ */\n+ template<typename _Key, typename _Compare = less<_Key>,\n+\t typename _KeyContainer = vector<_Key>>\n+ class flat_set\n+ : private _Flat_set_impl<_Key, _Compare, _KeyContainer, false>\n+ {\n+ using _Impl = _Flat_set_impl<_Key, _Compare, _KeyContainer, false>;\n+ friend _Impl;\n+\n+ public:\n+ // types\n+ using typename _Impl::key_type;\n+ using typename _Impl::value_type;\n+ using typename _Impl::key_compare;\n+ using typename _Impl::reference;\n+ using typename _Impl::const_reference;\n+ using typename _Impl::size_type;\n+ using typename _Impl::difference_type;\n+ using typename _Impl::iterator;\n+ using typename _Impl::const_iterator;\n+ using typename _Impl::reverse_iterator;\n+ using typename _Impl::const_reverse_iterator;\n+ using typename _Impl::container_type;\n+ using typename _Impl::value_compare;\n+\n+ // constructors\n+ using _Impl::_Impl;\n+\n+ // iterators\n+ using _Impl::begin;\n+ using _Impl::end;\n+ using _Impl::rbegin;\n+ using _Impl::rend;\n+\n+ using _Impl::cbegin;\n+ using _Impl::cend;\n+ using _Impl::crbegin;\n+ using _Impl::crend;\n+\n+ // capacity\n+ using _Impl::empty;\n+ using _Impl::size;\n+ using _Impl::max_size;\n+\n+ // modifiers\n+ using _Impl::emplace;\n+ using _Impl::emplace_hint;\n+ using _Impl::insert;\n+ // using _Impl::insert_range;\n+ using _Impl::extract;\n+ using _Impl::replace;\n+ using _Impl::erase;\n+ using _Impl::swap;\n+ using _Impl::clear;\n+\n+ // observers\n+ using _Impl::key_comp;\n+ using _Impl::value_comp;\n+\n+ // map operations\n+ using _Impl::find;\n+ using _Impl::count;\n+ using _Impl::contains;\n+ using _Impl::lower_bound;\n+ using _Impl::upper_bound;\n+ using _Impl::equal_range;\n+ };\n+\n+ template<typename _KeyContainer,\n+\t __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>\n+ flat_set(_KeyContainer, _Compare = _Compare())\n+ -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>\n+ flat_set(_KeyContainer, _Alloc)\n+ -> flat_set<typename _KeyContainer::value_type,\n+\t\tless<typename _KeyContainer::value_type>, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __not_allocator_like _Compare,\n+\t __allocator_for<_KeyContainer> _Alloc>\n+ flat_set(_KeyContainer, _Compare, _Alloc)\n+ -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<typename _KeyContainer,\n+\t __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>\n+ flat_set(sorted_unique_t, _KeyContainer, _Compare = _Compare())\n+ -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>\n+ flat_set(sorted_unique_t, _KeyContainer, _Alloc)\n+ -> flat_set<typename _KeyContainer::value_type,\n+\t\tless<typename _KeyContainer::value_type>, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __not_allocator_like _Compare,\n+\t __allocator_for<_KeyContainer> _Alloc>\n+ flat_set(sorted_unique_t, _KeyContainer, _Compare, _Alloc)\n+ -> flat_set<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<__has_input_iter_cat _InputIterator,\n+\t __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>\n+ flat_set(_InputIterator, _InputIterator, _Compare = _Compare())\n+ -> flat_set<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;\n+\n+ template<__has_input_iter_cat _InputIterator,\n+\t __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>\n+ flat_set(sorted_unique_t, _InputIterator, _InputIterator, _Compare = _Compare())\n+ -> flat_set<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;\n+\n+ template<ranges::input_range _Rg,\n+\t __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>,\n+\t __allocator_like _Alloc = allocator<ranges::range_value_t<_Rg>>>\n+ flat_set(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())\n+ -> flat_set<ranges::range_value_t<_Rg>, _Compare,\n+\t\tvector<ranges::range_value_t<_Rg>,\n+\t\t __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;\n+\n+ template<ranges::input_range _Rg, __allocator_like _Alloc>\n+ flat_set(from_range_t, _Rg&&, _Alloc)\n+ -> flat_set<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>,\n+\t\tvector<ranges::range_value_t<_Rg>,\n+\t\t __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;\n+\n+ template<typename _Key, __not_allocator_like _Compare = less<_Key>>\n+ flat_set(initializer_list<_Key>, _Compare = _Compare())\n+ -> flat_set<_Key, _Compare>;\n+\n+ template<typename _Key, __not_allocator_like _Compare = less<_Key>>\n+ flat_set(sorted_unique_t, initializer_list<_Key>, _Compare = _Compare())\n+ -> flat_set<_Key, _Compare>;\n+\n+ template<typename _Key, typename _Compare,\n+\t typename _KeyContainer, typename _Alloc>\n+ struct uses_allocator<flat_set<_Key, _Compare, _KeyContainer>, _Alloc>\n+ : bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>\n+ { };\n+\n+ /* Class template flat_multiset - container adaptor\n+ *\n+ * @ingroup\n+ */\n+ template<typename _Key, typename _Compare = less<_Key>,\n+\t typename _KeyContainer = vector<_Key>>\n+ class flat_multiset\n+ : private _Flat_set_impl<_Key, _Compare, _KeyContainer, true>\n+ {\n+ using _Impl = _Flat_set_impl<_Key, _Compare, _KeyContainer, true>;\n+ friend _Impl;\n+\n+ public:\n+ // types\n+ using typename _Impl::key_type;\n+ using typename _Impl::value_type;\n+ using typename _Impl::key_compare;\n+ using typename _Impl::reference;\n+ using typename _Impl::const_reference;\n+ using typename _Impl::size_type;\n+ using typename _Impl::difference_type;\n+ using typename _Impl::iterator;\n+ using typename _Impl::const_iterator;\n+ using typename _Impl::reverse_iterator;\n+ using typename _Impl::const_reverse_iterator;\n+ using typename _Impl::container_type;\n+ using typename _Impl::value_compare;\n+\n+ // constructors\n+ using _Impl::_Impl;\n+\n+ // iterators\n+ using _Impl::begin;\n+ using _Impl::end;\n+ using _Impl::rbegin;\n+ using _Impl::rend;\n+\n+ using _Impl::cbegin;\n+ using _Impl::cend;\n+ using _Impl::crbegin;\n+ using _Impl::crend;\n+\n+ // capacity\n+ using _Impl::empty;\n+ using _Impl::size;\n+ using _Impl::max_size;\n+\n+ // modifiers\n+ using _Impl::emplace;\n+ using _Impl::emplace_hint;\n+ using _Impl::insert;\n+ // using _Impl::insert_range;\n+ using _Impl::extract;\n+ using _Impl::replace;\n+ using _Impl::erase;\n+ using _Impl::swap;\n+ using _Impl::clear;\n+\n+ // observers\n+ using _Impl::key_comp;\n+ using _Impl::value_comp;\n+\n+ // map operations\n+ using _Impl::find;\n+ using _Impl::count;\n+ using _Impl::contains;\n+ using _Impl::lower_bound;\n+ using _Impl::upper_bound;\n+ using _Impl::equal_range;\n+ };\n+\n+ template<typename _KeyContainer,\n+\t __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>\n+ flat_multiset(_KeyContainer, _Compare = _Compare())\n+ -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>\n+ flat_multiset(_KeyContainer, _Alloc)\n+ -> flat_multiset<typename _KeyContainer::value_type,\n+\t\t less<typename _KeyContainer::value_type>, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __not_allocator_like _Compare,\n+\t __allocator_for<_KeyContainer> _Alloc>\n+ flat_multiset(_KeyContainer, _Compare, _Alloc)\n+ -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<typename _KeyContainer,\n+\t __not_allocator_like _Compare = less<typename _KeyContainer::value_type>>\n+ flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare = _Compare())\n+ -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __allocator_for<_KeyContainer> _Alloc>\n+ flat_multiset(sorted_equivalent_t, _KeyContainer, _Alloc)\n+ -> flat_multiset<typename _KeyContainer::value_type,\n+\t\t less<typename _KeyContainer::value_type>, _KeyContainer>;\n+\n+ template<typename _KeyContainer, __not_allocator_like _Compare,\n+\t __allocator_for<_KeyContainer> _Alloc>\n+ flat_multiset(sorted_equivalent_t, _KeyContainer, _Compare, _Alloc)\n+ -> flat_multiset<typename _KeyContainer::value_type, _Compare, _KeyContainer>;\n+\n+ template<__has_input_iter_cat _InputIterator,\n+\t __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>\n+ flat_multiset(_InputIterator, _InputIterator, _Compare = _Compare())\n+ -> flat_multiset<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;\n+\n+ template<__has_input_iter_cat _InputIterator,\n+\t __not_allocator_like _Compare = less<__iter_key_t<_InputIterator>>>\n+ flat_multiset(sorted_equivalent_t, _InputIterator, _InputIterator, _Compare = _Compare())\n+ -> flat_multiset<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, _Compare>;\n+\n+ template<ranges::input_range _Rg,\n+\t __not_allocator_like _Compare = less<ranges::range_value_t<_Rg>>,\n+\t __allocator_like _Alloc = allocator<ranges::range_value_t<_Rg>>>\n+ flat_multiset(from_range_t, _Rg&&, _Compare = _Compare(), _Alloc = _Alloc())\n+ -> flat_multiset<ranges::range_value_t<_Rg>, _Compare,\n+\t\t vector<ranges::range_value_t<_Rg>,\n+\t\t\t __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;\n+\n+ template<ranges::input_range _Rg, __allocator_like _Alloc>\n+ flat_multiset(from_range_t, _Rg&&, _Alloc)\n+ -> flat_multiset<ranges::range_value_t<_Rg>, less<ranges::range_value_t<_Rg>>,\n+\t\t vector<ranges::range_value_t<_Rg>,\n+\t\t\t __alloc_rebind<_Alloc, ranges::range_value_t<_Rg>>>>;\n+\n+ template<typename _Key, __not_allocator_like _Compare = less<_Key>>\n+ flat_multiset(initializer_list<_Key>, _Compare = _Compare())\n+ -> flat_multiset<_Key, _Compare>;\n+\n+ template<typename _Key, __not_allocator_like _Compare = less<_Key>>\n+ flat_multiset(sorted_equivalent_t, initializer_list<_Key>, _Compare = _Compare())\n+ -> flat_multiset<_Key, _Compare>;\n+\n+ template<typename _Key, typename _Compare,\n+\t typename _KeyContainer, typename _Alloc>\n+ struct uses_allocator<flat_multiset<_Key, _Compare, _KeyContainer>, _Alloc>\n+ : bool_constant<uses_allocator_v<_KeyContainer, _Alloc>>\n+ { };\n+\n+_GLIBCXX_END_NAMESPACE_VERSION\n+} // namespace std\n+#endif // __cpp_lib_flat_set\n+#endif // _GLIBCXX_FLAT_SET\ndiff --git a/libstdc++-v3/src/c++23/std.cc.in b/libstdc++-v3/src/c++23/std.cc.in\nindex 0225badeaacc..abec89908ab5 100644\n--- a/libstdc++-v3/src/c++23/std.cc.in\n+++ b/libstdc++-v3/src/c++23/std.cc.in\n@@ -1275,6 +1275,16 @@ export namespace std\n #endif\n \n // <flat_set>\n+#if __cpp_lib_flat_set\n+export namespace std\n+{\n+ using std::flat_set;\n+ using std::sorted_equivalent;\n+ using std::sorted_equivalent_t;\n+ using std::sorted_unique;\n+ using std::sorted_unique_t;\n+}\n+#endif\n \n // <format>\n export namespace std\ndiff --git a/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc\nnew file mode 100644\nindex 000000000000..c05cda33b05d\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/flat_multiset/1.cc\n@@ -0,0 +1,131 @@\n+// { dg-do run { target c++23 } }\n+\n+#include <flat_set>\n+#include <deque>\n+#include <vector>\n+#include <testsuite_allocator.h>\n+#include <testsuite_hooks.h>\n+\n+template<template<class> class Sequence>\n+void\n+test01()\n+{\n+ std::flat_multiset<int, std::less<int>, Sequence<int>> m;\n+ static_assert( std::ranges::random_access_range<decltype(m)> );\n+\n+ m.insert(1);\n+ m.insert(2);\n+ m.insert(3);\n+ m.insert(1);\n+ m.insert(2);\n+ m.insert(3);\n+ m.insert(0);\n+ VERIFY( m.size() == 7 );\n+ VERIFY( std::ranges::equal(m, (int[]){0, 1, 1, 2, 2, 3, 3}) );\n+\n+ m.clear();\n+ m.insert(m.begin(), 0);\n+ m.insert(m.begin(), 1);\n+ m.insert(m.begin(), 2);\n+ m.insert(m.begin(), 3);\n+ m.insert(m.begin(), 1);\n+ m.insert(m.begin(), 2);\n+ m.insert(m.begin(), 3);\n+ m.insert(m.begin(), 0);\n+ VERIFY( std::ranges::equal(m, (int[]){0, 0, 1, 1, 2, 2, 3, 3}) );\n+\n+ m.clear();\n+ m = {10,10};\n+ VERIFY( m.size() == 2 );\n+ m.insert({11,12,11});\n+ VERIFY( m.size() == 5 );\n+}\n+\n+void\n+test02()\n+{\n+ std::flat_multiset<int, std::greater<int>> m;\n+ static_assert( std::ranges::random_access_range<decltype(m)> );\n+\n+ auto r = m.insert(1);\n+ VERIFY( *r == 1 );\n+ r = m.insert(2);\n+ VERIFY( *r == 2 );\n+ r = m.insert(3);\n+ VERIFY( *r == 3 );\n+ r = m.insert(1);\n+ VERIFY( *r == 1 );\n+ r = m.insert(2);\n+ VERIFY( *r == 2 );\n+ r = m.insert(3);\n+ VERIFY( *r == 3 );\n+ VERIFY( m.size() == 6 );\n+ VERIFY( std::ranges::equal(m, (int[]){3, 3, 2, 2, 1, 1}) );\n+\n+ VERIFY( m.contains(3) && !m.contains(7) );\n+ VERIFY( m.count(3) == 2 );\n+}\n+\n+void\n+test03()\n+{\n+ std::flat_set<int> m;\n+ m = {1, 3, 5};\n+ m.insert({7, 9});\n+\n+ auto it = m.find(0);\n+ VERIFY( it == m.end() );\n+ it = m.find(9);\n+ VERIFY( it == m.end()-1 );\n+\n+ const auto n = m;\n+ VERIFY( m == m );\n+ VERIFY( m == n );\n+\n+ m.erase(m.begin());\n+ m.erase(5);\n+ m.erase(m.end()-2, m.end());\n+ VERIFY( std::ranges::equal(m, (int[]){3}) );\n+ VERIFY( m != n );\n+ VERIFY( n < m );\n+\n+ m = n;\n+ erase_if(m, [](const auto& k) { return k < 5 || k > 5; });\n+ VERIFY( std::ranges::equal(m, (int[]){5}) );\n+}\n+\n+void\n+test04()\n+{\n+ using vector = std::vector<int, __gnu_test::uneq_allocator<int>>;\n+ vector v = {1, 2, 3};\n+ __gnu_test::uneq_allocator<int> alloc(42);\n+\n+ using flat_multiset = std::flat_multiset<int, std::less<int>, vector>;\n+ flat_multiset m1(alloc);\n+ VERIFY( std::move(m1).extract().get_allocator().get_personality() == 42 );\n+\n+ flat_multiset m2(v, alloc);\n+ VERIFY( std::move(m2).extract().get_allocator().get_personality() == 42 );\n+\n+ flat_multiset m2(std::sorted_equivalent_t{}, v, alloc);\n+ VERIFY( std::move(m2).extract().get_allocator().get_personality() == 42 );\n+\n+ alloc = __gnu_test::uneq_allocator<int>(43);\n+ flat_multiset m4(m2, alloc);\n+ VERIFY( std::move(m4).extract().get_allocator().get_personality() == 43 );\n+\n+ alloc = __gnu_test::uneq_allocator<int>(44);\n+ flat_multiset m5(std::move(m4), alloc);\n+ VERIFY( std::move(m5).extract().get_allocator().get_personality() == 44 );\n+}\n+\n+int\n+main()\n+{\n+ test01<std::vector>();\n+ test01<std::deque>();\n+ test02();\n+ test03();\n+ test04();\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/flat_set/1.cc b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc\nnew file mode 100644\nindex 000000000000..13c71f4c1df0\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/flat_set/1.cc\n@@ -0,0 +1,146 @@\n+// { dg-do run { target c++23 } }\n+\n+#include <flat_set>\n+\n+#if __cpp_lib_flat_set != 202207L\n+# error \"Feature-test macro __cpp_lib_flat_set has wrong value in <flat_set>\"\n+#endif\n+\n+#include <deque>\n+#include <vector>\n+#include <testsuite_allocator.h>\n+#include <testsuite_hooks.h>\n+\n+template<template<class> class Sequence>\n+void\n+test01()\n+{\n+ std::flat_set<int, std::less<int>, Sequence<int>> m;\n+ static_assert( std::ranges::random_access_range<decltype(m)> );\n+\n+ m.insert(1);\n+ m.insert(2);\n+ m.insert(3);\n+ m.insert(1);\n+ m.insert(2);\n+ m.insert(3);\n+ m.insert(0);\n+ VERIFY( m.size() == 4 );\n+ VERIFY( std::ranges::equal(m, (int[]){0, 1, 2, 3}) );\n+\n+ for (int i = 0; i < 4; i++)\n+ {\n+ m.clear();\n+ m.insert(m.end(), (i + 0) % 4);\n+ m.insert(m.end(), (i + 1) % 4);\n+ m.insert(m.end(), (i + 2) % 4);\n+ m.insert(m.end(), (i + 3) % 4);\n+ m.insert(m.begin() + i, 1);\n+ m.insert(m.begin() + i, 2);\n+ m.insert(m.begin() + i, 3);\n+ m.insert(m.begin() + i, 0);\n+ VERIFY( std::ranges::equal(m, (int[]){0, 1, 2, 3}) );\n+ }\n+\n+ m.clear();\n+ m = {10,10};\n+ VERIFY( m.size() == 1 );\n+ m.insert({11, 12, 11});\n+ VERIFY( m.size() == 3 );\n+ VERIFY( m.end()[-1] == 12 );\n+\n+ auto m_copy = m;\n+ VERIFY( m_copy == m );\n+ m_copy.operator=({12, 11, 10});\n+ VERIFY( m_copy == m );\n+}\n+\n+void\n+test02()\n+{\n+ std::flat_set<int, std::greater<int>> m;\n+ static_assert( std::ranges::random_access_range<decltype(m)> );\n+\n+ auto r = m.insert(1);\n+ VERIFY( *r.first == 1 && r.second );\n+ r = m.insert(2);\n+ VERIFY( *r.first == 2 && r.second );\n+ r = m.insert(3);\n+ VERIFY( *r.first == 3 && r.second );\n+ r = m.insert(1);\n+ VERIFY( *r.first == 1 && !r.second );\n+ r = m.insert(2);\n+ VERIFY( *r.first == 2 && !r.second );\n+ r = m.insert(3);\n+ VERIFY( *r.first == 3 && !r.second );\n+ m.insert(0);\n+ VERIFY( m.size() == 4 );\n+ VERIFY( std::ranges::equal(m, (int[]){3, 2, 1, 0}) );\n+\n+ VERIFY( m.contains(3) && !m.contains(7) );\n+ VERIFY( m.count(3) == 1 );\n+}\n+\n+void\n+test03()\n+{\n+ std::flat_set<int> m;\n+ m = {1, 3, 5};\n+ m.insert({7, 9});\n+\n+ auto it = m.find(0);\n+ VERIFY( it == m.end() );\n+ it = m.find(9);\n+ VERIFY( it == m.end()-1 );\n+\n+ const auto n = m;\n+ VERIFY( m == m );\n+ VERIFY( m == n );\n+\n+ m.erase(m.begin());\n+ m.erase(5);\n+ m.erase(m.end()-2, m.end());\n+ VERIFY( std::ranges::equal(m, (int[]){3}) );\n+ VERIFY( m != n );\n+ VERIFY( n < m );\n+\n+ m = n;\n+ erase_if(m, [](const auto& k) { return k < 5 || k > 5; });\n+ VERIFY( std::ranges::equal(m, (int[]){5}) );\n+}\n+\n+void\n+test04()\n+{\n+ using vector = std::vector<int, __gnu_test::uneq_allocator<int>>;\n+ vector v = {1, 2, 3};\n+ __gnu_test::uneq_allocator<int> alloc(42);\n+\n+ using flat_set = std::flat_set<int, std::less<int>, vector>;\n+ flat_set m1(alloc);\n+ VERIFY( std::move(m1).extract().get_allocator().get_personality() == 42 );\n+\n+ flat_set m2(v, alloc);\n+ VERIFY( std::move(m2).extract().get_allocator().get_personality() == 42 );\n+\n+ flat_set m3(std::sorted_unique_t{}, v, alloc);\n+ VERIFY( std::move(m3).extract().get_allocator().get_personality() == 42 );\n+\n+ alloc = __gnu_test::uneq_allocator<int>(43);\n+ flat_set m4(m3, alloc);\n+ VERIFY( std::move(m4).extract().get_allocator().get_personality() == 43 );\n+\n+ alloc = __gnu_test::uneq_allocator<int>(44);\n+ flat_set m5(std::move(m4), alloc);\n+ VERIFY( std::move(m5).extract().get_allocator().get_personality() == 44 );\n+}\n+\n+int\n+main()\n+{\n+ test01<std::vector>();\n+ test01<std::deque>();\n+ test02();\n+ test03();\n+ test04();\n+}\n", "prefixes": [ "v1", "3/3" ] }