Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2194811/?format=api
{ "id": 2194811, "url": "http://patchwork.ozlabs.org/api/patches/2194811/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260210004855.1562521-1-ncm@cantrip.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": "<20260210004855.1562521-1-ncm@cantrip.org>", "list_archive_url": null, "date": "2026-02-10T00:47:20", "name": "[PATCHv6] libstdc++: container heterogenous insertion (P2363) [PR117402]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "e6538ce261207107f771e917d655e4e31149d125", "submitter": { "id": 90892, "url": "http://patchwork.ozlabs.org/api/people/90892/?format=api", "name": "Nathan Myers", "email": "ncm@cantrip.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260210004855.1562521-1-ncm@cantrip.org/mbox/", "series": [ { "id": 491585, "url": "http://patchwork.ozlabs.org/api/series/491585/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=491585", "date": "2026-02-10T00:47:20", "name": "[PATCHv6] libstdc++: container heterogenous insertion (P2363) [PR117402]", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/491585/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2194811/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2194811/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;\n dmarc=none (p=none dis=none) header.from=cantrip.org", "sourceware.org; spf=fail smtp.mailfrom=cantrip.org", "server2.sourceware.org;\n arc=none smtp.remote-ip=205.139.111.44" ], "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 4f92yk2Dgfz1xtr\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 10 Feb 2026 11:49:47 +1100 (AEDT)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 345464BBC0FF\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 10 Feb 2026 00:49:40 +0000 (GMT)", "from us-smtp-delivery-44.mimecast.com\n (us-smtp-delivery-44.mimecast.com [205.139.111.44])\n by sourceware.org (Postfix) with ESMTP id BACA64BBC0FF\n for <gcc-patches@gcc.gnu.org>; Tue, 10 Feb 2026 00:49:04 +0000 (GMT)", "from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com\n (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by\n relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3,\n cipher=TLS_AES_256_GCM_SHA384) id us-mta-444-jmHGtdV3MeqLNHmnvHpHgw-1; Mon,\n 09 Feb 2026 19:49:00 -0500", "from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com\n (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS\n id 119BC18003F5; Tue, 10 Feb 2026 00:49:00 +0000 (UTC)", "from redhat.redhat.com (unknown [10.2.16.56])\n by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP\n id 65D9219560A3; Tue, 10 Feb 2026 00:48:57 +0000 (UTC)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 345464BBC0FF", "OpenDKIM Filter v2.11.0 sourceware.org BACA64BBC0FF" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org BACA64BBC0FF", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org BACA64BBC0FF", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1770684544; cv=none;\n b=frPBYn/Sg38c4YCAt9E7k3wUy1FstiM6ztBuO8wXOt3XboidHr87BFyVt0Gfh14BOposC+6Ksx8QPIHzwc17iNqQtV3u7jLCCqL+9qz1z0NyRc/EpGnyuOl2ZndCJkNQSIeR4tiMLMPswTsH7PnPq24gf0YXDrWdveqZ/Ul/Bw0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1770684544; c=relaxed/simple;\n bh=Qn69IrFzInGKHT5Q6VDWRpCClOxsvedDcZIOJOQ4K0Y=;\n h=From:To:Subject:Date:Message-ID:MIME-Version;\n b=ODcgzGkhFlDcbFI4ZK5LTSiww1/J3Xth5qFz5Yac3AiL7lwLfnO7hJzmIG0hSW/KE4aP4SSThq6Hpgew4yYvV9I/atUUM72QCOk4jQeljd+j2ZlgVb4hyZ9DsF82UsoBD74jyJdTjxXfhC2bVENqvS+RI+8jENdkx7BpSogSjQ0=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "X-MC-Unique": "jmHGtdV3MeqLNHmnvHpHgw-1", "X-Mimecast-MFC-AGG-ID": "jmHGtdV3MeqLNHmnvHpHgw_1770684540", "From": "Nathan Myers <ncm@cantrip.org>", "To": "gcc-patches@gcc.gnu.org,\n\tlibstdc++@gcc.gnu.org", "Subject": "[PATCHv6] libstdc++: container heterogenous insertion (P2363)\n [PR117402]", "Date": "Mon, 9 Feb 2026 19:47:20 -0500", "Message-ID": "<20260210004855.1562521-1-ncm@cantrip.org>", "MIME-Version": "1.0", "X-Scanned-By": "MIMEDefang 3.0 on 10.30.177.12", "X-Mimecast-Spam-Score": "0", "X-Mimecast-MFC-PROC-ID": "--FgePuH9hm3sOxwmknLIEYNTBdzlgKTa9eproqRnaE_1770684540", "X-Mimecast-Originator": "cantrip.org", "Content-Transfer-Encoding": "quoted-printable", "content-type": "text/plain; charset=WINDOWS-1252; x-default=true", "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>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "Changes in v6: (Note, this was recently mis-posted as v5.)\n - More testing for op[] and at(): move-from key argument when and\n only when permitted.\n\nChanges in v5:\n - Fix typos in set/modifiers/hetero/insert.cc.\n - Fix chart in commit message.\n\nChanges in v4:\n - Rebase on committed P2077 erasures.\n - Remove conditional compilation on impl helpers in\n bits/stl_tree.h, hashtable.h, hashtable_policy.h.\n - Regularize ChangeLog format.\n - Test propagation of heterogeneous key's value category\n through to conversion to key_type.\n - Test propagation of variadic-arguments' value categories\n from try_emplace through to underlying constructors.\n - Regularize template argument name s/_Mapped/_Obj/.\n\nChanges in v3:\n - Make tests run, and pass.\n - Note added members in Changelog.\n\nChange in v2: fix remaining regression, SEGV in 92878_92947.cc.\n\nImplements P2353R5 \"Extending associative containers with the\nremaining heterogeneous overloads\". Adds overloads templated on\nheterogeneous key types for several members of associative\ncontainers, particularly insertions:\n\n un- un- un- unordered\n set map mset mmap set map mset mmap\n @ . . . @ . . . insert\n . @ . . . @ . . op[], at, try_emplace,\n insert_or_assign\n . . . . @ @ @ @ bucket\n\n(Nothing is added to the multiset or multimap tree containers.)\nAll the insert*() and try_emplace() members also get a hinted\noverload. The at() members get const and non-const overloads.\n\nThe new overloads enforce concept __heterogeneous_tree_key or\n__heterogeneous_hash_key, as in P2077, to enforce that the\nfunction objects provided meet requirements, and that the key\nsupplied is not an iterator or the native key. Insertions\nimplicitly construct the required key_type object from the\nargument, by move where permitted.\n\nDoxygen annotations are improved.\n\nlibstdc++-v3/ChangeLog:\n\tPR libstdc++/117402\n\t* include/bits/stl_map.h (operator[], at (2x), try_emplace (2x),\n\tinsert_or_assign (2x)): Add overloads.\n\t* include/bits/unordered_map.h: Same, plus...\n\t(bucket (2x)): Add overloads.\n\t* include/bits/stl_set.h (insert (2x)): Add overloads.\n\t* include/bits/unordered_set.h: Same, plus...\n\t(bucket (2x)): Add overloads.\n\t* include/bits/hashtable.h (_M_bucket_tr, _M_insert_tr): Define.\n\t* include/bits/hashtable_policy.h (_M_index_to_tr, _M_at_tr (2x),\n\t_M_index_to_tr): Define.\n\t* include/bits/stl_tree.h (_M_get_insert_unique_pos_tr,\n\t_M_get_insert_hint_unique_pos_tr): Define.\n\t* include/bits/version.def (associative_heterogeneous_insertion):\n\tDefine.\n\t* include/bits/version.h: Regenerate.\n\t* include/std/map (__glibcxx_want_associative_heterogeneous_insertion):\n\tDefine macro.\n\t* include/std/set: Same.\n\t* include/std/unordered_map: Same.\n\t* include/std/unordered_set: Same.\n\t* testsuite/23_containers/map/modifiers/hetero/insert.cc: New tests.\n\t* testsuite/23_containers/set/modifiers/hetero/insert.cc: Same.\n\t* testsuite/23_containers/unordered_map/modifiers/hetero/insert.cc:\n\tSame.\n\t* testsuite/23_containers/unordered_multimap/modifiers/hetero/insert.cc:\n\tSame.\n\t* testsuite/23_containers/unordered_multiset/modifiers/hetero/insert.cc:\n\tSame.\n\t* testsuite/23_containers/unordered_set/modifiers/hetero/insert.cc:\n\tSame.\n---\n libstdc++-v3/include/bits/hashtable.h | 27 ++\n libstdc++-v3/include/bits/hashtable_policy.h | 60 ++-\n libstdc++-v3/include/bits/stl_map.h | 126 ++++++-\n libstdc++-v3/include/bits/stl_set.h | 21 ++\n libstdc++-v3/include/bits/stl_tree.h | 106 +++++-\n libstdc++-v3/include/bits/unordered_map.h | 96 +++++\n libstdc++-v3/include/bits/unordered_set.h | 32 ++\n libstdc++-v3/include/bits/version.def | 8 +\n libstdc++-v3/include/bits/version.h | 10 +\n libstdc++-v3/include/std/map | 1 +\n libstdc++-v3/include/std/set | 1 +\n libstdc++-v3/include/std/unordered_map | 1 +\n libstdc++-v3/include/std/unordered_set | 1 +\n .../map/modifiers/hetero/insert.cc | 341 +++++++++++++++++\n .../set/modifiers/hetero/insert.cc | 120 ++++++\n .../unordered_map/modifiers/hetero/insert.cc | 353 ++++++++++++++++++\n .../modifiers/hetero/insert.cc | 57 +++\n .../modifiers/hetero/insert.cc | 56 +++\n .../unordered_set/modifiers/hetero/insert.cc | 134 +++++++\n 19 files changed, 1544 insertions(+), 7 deletions(-)\n create mode 100644 libstdc++-v3/testsuite/23_containers/map/modifiers/hetero/insert.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/set/modifiers/hetero/insert.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/hetero/insert.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_multimap/modifiers/hetero/insert.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_multiset/modifiers/hetero/insert.cc\n create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/hetero/insert.cc", "diff": "diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h\nindex 48695c013f3..fc7a5aae595 100644\n--- a/libstdc++-v3/include/bits/hashtable.h\n+++ b/libstdc++-v3/include/bits/hashtable.h\n@@ -700,6 +700,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n bucket(const key_type& __k) const\n { return _M_bucket_index(this->_M_hash_code(__k)); }\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26, P2363\n+ template <typename _Kt>\n+\tsize_type\n+\t_M_bucket_tr(const _Kt& __k) const\n+\t{ return _M_bucket_index(this->_M_hash_code_tr(__k)); }\n+#endif\n+\n local_iterator\n begin(size_type __bkt)\n {\n@@ -1097,6 +1104,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \tstd::pair<iterator, bool>\n \ttry_emplace(const_iterator, _KType&& __k, _Args&&... __args)\n \t{\n+\t // Note we ignore the hint argument.\n \t __hash_code __code;\n \t size_type __bkt;\n \t if (auto __loc = _M_locate(__k))\n@@ -1117,6 +1125,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \t __node._M_node = nullptr;\n \t return { __it, true };\n \t}\n+\n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26, P2363\n+ template<typename _Kt>\n+\tstd::pair<iterator, bool>\n+\t_M_insert_tr(_Kt&& __k)\n+\t{\n+\t auto __loc = _M_locate_tr(__k);\n+\t if (__loc)\n+\t return { iterator(__loc), false };\n+\n+\t _Scoped_node __node(\n+\t this->_M_allocate_node(std::forward<_Kt>(__k)), this);\n+\t auto __it = _M_insert_unique_node(\n+\t __loc._M_bucket_index, __loc._M_hash_code, __node._M_node);\n+\t __node._M_node = nullptr;\n+\t return { __it, true };\n+\t}\n+#endif\n #endif\n \n void\n@@ -2363,6 +2389,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION\n \t__node._M_node = nullptr;\n \treturn { __pos, true };\n }\n+\n #pragma GCC diagnostic pop\n \n template<typename _Key, typename _Value, typename _Alloc,\ndiff --git a/libstdc++-v3/include/bits/hashtable_policy.h b/libstdc++-v3/include/bits/hashtable_policy.h\nindex 6d7bde1e785..92fa6e82e5b 100644\n--- a/libstdc++-v3/include/bits/hashtable_policy.h\n+++ b/libstdc++-v3/include/bits/hashtable_policy.h\n@@ -872,6 +872,33 @@ namespace __detail\n \t __throw_out_of_range(__N(\"unordered_map::at\"));\n \treturn __ite->second;\n }\n+\n+ // op[] for transparent heterogeneous key\n+ template <typename _Kt>\n+\tmapped_type&\n+\t_M_index_to_tr(const _Kt& __k);\n+\n+ // _GLIBCXX_RESOLVE_LIB_DEFECTS\n+ // DR 761. unordered_map needs an at() member function.\n+ template <typename _Kt>\n+\tmapped_type&\n+\t_M_at_tr(const _Kt& __k)\n+\t{\n+\t auto __ite = static_cast<__hashtable*>(this)->_M_find_tr(__k);\n+\t if (!__ite._M_cur)\n+\t __throw_out_of_range(__N(\"unordered_map::at\"));\n+\t return __ite->second;\n+\t}\n+\n+ template <typename _Kt>\n+\tconst mapped_type&\n+\t_M_at_tr(const _Kt& __k) const\n+\t{\n+\t auto __ite = static_cast<const __hashtable*>(this)->_M_find_tr(__k);\n+\t if (!__ite._M_cur)\n+\t __throw_out_of_range(__N(\"unordered_map::at\"));\n+\t return __ite->second;\n+\t}\n };\n \n template<typename _Key, typename _Val, typename _Alloc, typename _Equal,\n@@ -901,6 +928,33 @@ namespace __detail\n return __pos->second;\n }\n \n+ // op[] for heterogeneous keys\n+ template<typename _Key, typename _Val, typename _Alloc, typename _Equal,\n+\t typename _Hash, typename _RangeHash, typename _Unused,\n+\t typename _RehashPolicy, typename _Traits>\n+ template <typename _Kt>\n+ auto\n+ _Map_base<_Key, pair<const _Key, _Val>, _Alloc, _Select1st, _Equal,\n+\t\t_Hash, _RangeHash, _Unused, _RehashPolicy, _Traits, true>::\n+ _M_index_to_tr(const _Kt& __k)\n+ -> mapped_type&\n+ {\n+ __hashtable* __h = static_cast<__hashtable*>(this);\n+ __hash_code __code = __h->_M_hash_code_tr(__k);\n+ size_t __bkt = __h->_M_bucket_index(__code);\n+ if (auto __node = __h->_M_find_node_tr(__bkt, __k, __code))\n+\treturn __node->_M_v().second;\n+\n+ typename __hashtable::_Scoped_node __node {\n+\t__h, std::piecewise_construct,\n+\tstd::tuple<key_type>(__k), std::tuple<>()\n+ };\n+ auto __pos\n+\t= __h->_M_insert_unique_node(__bkt, __code, __node._M_node);\n+ __node._M_node = nullptr;\n+ return __pos->second;\n+ }\n+\n template<typename _Key, typename _Val, typename _Alloc, typename _Equal,\n \t typename _Hash, typename _RangeHash, typename _Unused,\n \t typename _RehashPolicy, typename _Traits>\n@@ -1413,8 +1467,7 @@ namespace __detail\n template<typename _Kt>\n \tbool\n \t_M_key_equals_tr(const _Kt& __k,\n-\t\t\t const _Hash_node_value<_Value,\n-\t\t\t\t\t __hash_cached::value>& __n) const\n+\t const _Hash_node_value<_Value, __hash_cached::value>& __n) const\n \t{\n \t static_assert(\n \t __is_invocable<const _Equal&, const _Kt&, const _Key&>{},\n@@ -1439,8 +1492,7 @@ namespace __detail\n template<typename _Kt>\n \tbool\n \t_M_equals_tr(const _Kt& __k, __hash_code __c,\n-\t\t const _Hash_node_value<_Value,\n-\t\t\t\t\t __hash_cached::value>& __n) const\n+\t const _Hash_node_value<_Value, __hash_cached::value>& __n) const\n \t{\n \t if constexpr (__hash_cached::value)\n \t if (__c != __n._M_hash_code)\ndiff --git a/libstdc++-v3/include/bits/stl_map.h b/libstdc++-v3/include/bits/stl_map.h\nindex 4cb0c982c3d..f4b0982af72 100644\n--- a/libstdc++-v3/include/bits/stl_map.h\n+++ b/libstdc++-v3/include/bits/stl_map.h\n@@ -511,6 +511,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n max_size() const _GLIBCXX_NOEXCEPT\n { return _M_t.max_size(); }\n \n+ ///@{\n // [23.3.1.2] element access\n /**\n * @brief Subscript ( @c [] ) access to %map data.\n@@ -560,6 +561,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n }\n #endif\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt>\n+\tmapped_type&\n+\toperator[](_Kt&& __k)\n+\t{ return try_emplace(std::forward<_Kt>(__k)).first->second; }\n+#endif\n+ ///@}\n+\n+ ///@{\n // _GLIBCXX_RESOLVE_LIB_DEFECTS\n // DR 464. Suggestion for new member functions in standard containers.\n /**\n@@ -578,6 +588,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \treturn (*__i).second;\n }\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt>\n+\tmapped_type&\n+\tat(const _Kt& __k)\n+\t{\n+\t iterator __i = lower_bound(__k);\n+\t if (__i == end() || key_comp()(__k, (*__i).first))\n+\t __throw_out_of_range(__N(\"map::at\"));\n+\t return (*__i).second;\n+\t}\n+#endif\n+\n const mapped_type&\n at(const key_type& __k) const\n {\n@@ -587,6 +609,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \treturn (*__i).second;\n }\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt>\n+\tconst mapped_type&\n+\tat(const _Kt& __k) const\n+\t{\n+\t const_iterator __i = lower_bound(__k);\n+\t if (__i == end() || key_comp()(__k, (*__i).first))\n+\t __throw_out_of_range(__N(\"map::at\"));\n+\t return (*__i).second;\n+\t}\n+#endif\n+ ///@}\n+\n // modifiers\n #if __cplusplus >= 201103L\n /**\n@@ -728,6 +763,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n #endif // C++17\n \n #ifdef __glibcxx_map_try_emplace // C++ >= 17 && HOSTED\n+ ///@{\n /**\n * @brief Attempts to build and insert a std::pair into the %map.\n *\n@@ -781,6 +817,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t return {__i, false};\n \t}\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt, typename ..._Args>\n+\tpair<iterator, bool>\n+\ttry_emplace(_Kt&& __k, _Args&&... __args)\n+\t{\n+\t iterator __i = lower_bound(__k);\n+\t if (__i == end() || key_comp()(__k, (*__i).first))\n+\t {\n+\t __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct,\n+\t\tstd::forward_as_tuple(std::forward<_Kt>(__k)),\n+\t\tstd::forward_as_tuple(std::forward<_Args>(__args)...));\n+\t return {__i, true};\n+\t }\n+\t return {__i, false};\n+\t}\n+#endif\n+ ///@}\n+\n+ ///@{\n /**\n * @brief Attempts to build and insert a std::pair into the %map.\n *\n@@ -845,6 +900,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt, typename ..._Args>\n+\titerator\n+\ttry_emplace(const_iterator __hint, _Kt&& __k, _Args&&... __args)\n+\t{\n+\t iterator __i;\n+\t auto __true_hint = _M_t._M_get_insert_hint_unique_pos_tr(__hint, __k);\n+\t if (__true_hint.second)\n+\t __i = _M_t._M_emplace_hint_unique(iterator(__true_hint.second),\n+\t\tstd::piecewise_construct,\n+\t\tstd::forward_as_tuple(std::forward<_Kt>(__k)),\n+\t\tstd::forward_as_tuple(std::forward<_Args>(__args)...));\n+\t else\n+\t __i = iterator(__true_hint.first);\n+\t return __i;\n+\t}\n+#endif\n+ ///@}\n+\n+ ///@{\n /**\n * @brief Attempts to insert a std::pair into the %map.\n * @param __x Pair to be inserted (see std::make_pair for easy\n@@ -896,7 +971,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t return _M_t._M_emplace_unique(std::forward<_Pair>(__x));\n \t}\n #endif\n- /// @}\n+ ///@}\n \n #if __cplusplus >= 201103L\n /**\n@@ -929,6 +1004,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif\n \n+ ///@{\n /**\n * @brief Attempts to insert a std::pair into the %map.\n * @param __position An iterator that serves as a hint as to where the\n@@ -992,6 +1068,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t{ _M_t._M_insert_range_unique(__first, __last); }\n \n #if __cplusplus > 201402L\n+ ///@{\n /**\n * @brief Attempts to insert or assign a std::pair into the %map.\n * @param __k Key to use for finding a possibly existing pair in\n@@ -1046,6 +1123,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t return {__i, false};\n \t}\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt, typename _Obj>\n+\tpair<iterator, bool>\n+\tinsert_or_assign(_Kt&& __k, _Obj&& __obj)\n+\t{\n+\t iterator __i = lower_bound(__k);\n+\t if (__i == end() || key_comp()(__k, (*__i).first))\n+\t {\n+\t __i = _M_t._M_emplace_hint_unique(__i,\n+\t\tstd::piecewise_construct,\n+\t\tstd::forward_as_tuple(std::forward<_Kt>(__k)),\n+\t\tstd::forward_as_tuple(std::forward<_Obj>(__obj)));\n+\t return {__i, true};\n+\t }\n+\t (*__i).second = std::forward<_Obj>(__obj);\n+\t return {__i, false};\n+\t}\n+#endif\n+ ///@}\n+#endif\n+\n+#if __cplusplus > 201402L\n+ ///@{\n /**\n * @brief Attempts to insert or assign a std::pair into the %map.\n * @param __hint An iterator that serves as a hint as to where the\n@@ -1105,9 +1205,33 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t (*__i).second = std::forward<_Obj>(__obj);\n \t return __i;\n \t}\n+\n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<map> _Kt, typename _Obj>\n+\titerator\n+\tinsert_or_assign(const_iterator __hint, _Kt&& __k, _Obj&& __obj)\n+\t{\n+\t iterator __i;\n+\t auto __true_hint =\n+\t _M_t._M_get_insert_hint_unique_pos_tr(__hint, __k);\n+\t if (__true_hint.second)\n+\t {\n+\t return _M_t._M_emplace_hint_unique(\n+\t\titerator(__true_hint.second),\n+\t\tstd::piecewise_construct,\n+\t\tstd::forward_as_tuple(std::forward<_Kt>(__k)),\n+\t\tstd::forward_as_tuple(std::forward<_Obj>(__obj)));\n+\t }\n+\t __i = iterator(__true_hint.first);\n+\t (*__i).second = std::forward<_Obj>(__obj);\n+\t return __i;\n+\t}\n+#endif\n+ ///@}\n #endif\n \n #if __cplusplus >= 201103L\n+ ///@{\n // _GLIBCXX_RESOLVE_LIB_DEFECTS\n // DR 130. Associative erase should return an iterator.\n /**\ndiff --git a/libstdc++-v3/include/bits/stl_set.h b/libstdc++-v3/include/bits/stl_set.h\nindex d3a4c089110..d3e876039d8 100644\n--- a/libstdc++-v3/include/bits/stl_set.h\n+++ b/libstdc++-v3/include/bits/stl_set.h\n@@ -517,6 +517,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif\n \n+ ///@{\n /**\n * @brief Attempts to insert an element into the %set.\n * @param __x Element to be inserted.\n@@ -548,6 +549,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n }\n #endif\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<set> _Kt>\n+\tpair<iterator, bool>\n+\tinsert(_Kt&& __x)\n+\t{\n+\t auto __p = _M_t._M_insert_unique(std::forward<_Kt>(__x));\n+\t return {__p.first, __p.second};\n+\t}\n+#endif\n+ ///@}\n+\n+ ///@{\n /**\n * @brief Attempts to insert an element into the %set.\n * @param __position An iterator that serves as a hint as to where the\n@@ -577,6 +590,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n { return _M_t._M_insert_unique_(__position, std::move(__x)); }\n #endif\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_tree_key<set> _Kt>\n+\titerator\n+\tinsert(const_iterator __position, _Kt&& __x)\n+\t{ return _M_t._M_insert_unique_(__position, std::forward<_Kt>(__x)); }\n+#endif\n+ ///@}\n+\n /**\n * @brief A template function that attempts to insert a range\n * of elements.\ndiff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h\nindex 5d361b55028..ebe4810bcbc 100644\n--- a/libstdc++-v3/include/bits/stl_tree.h\n+++ b/libstdc++-v3/include/bits/stl_tree.h\n@@ -1459,6 +1459,10 @@ namespace __rb_tree\n pair<_Base_ptr, _Base_ptr>\n _M_get_insert_unique_pos(const key_type& __k);\n \n+ template <typename _Kt>\n+\tpair<_Base_ptr, _Base_ptr>\n+\t_M_get_insert_unique_pos_tr(const _Kt& __k);\n+\n pair<_Base_ptr, _Base_ptr>\n _M_get_insert_equal_pos(const key_type& __k);\n \n@@ -1466,6 +1470,11 @@ namespace __rb_tree\n _M_get_insert_hint_unique_pos(const_iterator __pos,\n \t\t\t\t const key_type& __k);\n \n+ template <typename _Kt>\n+\tpair<_Base_ptr, _Base_ptr>\n+\t_M_get_insert_hint_unique_pos_tr(\n+\t const_iterator __pos, const _Kt& __k);\n+\n pair<_Base_ptr, _Base_ptr>\n _M_get_insert_hint_equal_pos(const_iterator __pos,\n \t\t\t\t const key_type& __k);\n@@ -2060,7 +2069,7 @@ namespace __rb_tree\n _M_move_assign(_Rb_tree&, false_type);\n #endif\n \n-#if __glibcxx_node_extract // >= C++17\n+#ifdef __glibcxx_node_extract // >= C++17\n static _Node_ptr\n _S_adapt(typename _Node_alloc_traits::pointer __ptr)\n {\n@@ -2810,6 +2819,40 @@ namespace __rb_tree\n return _Res(__j._M_node, _Base_ptr());\n }\n \n+ template<typename _Key, typename _Val, typename _KeyOfValue,\n+\t typename _Compare, typename _Alloc>\n+ template <typename _Kt>\n+ pair<\n+\ttypename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n+\t _Base_ptr,\n+\ttypename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n+\t _Base_ptr>\n+ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n+ _M_get_insert_unique_pos_tr(const _Kt& __k)\n+ {\n+ typedef pair<_Base_ptr, _Base_ptr> _Res;\n+ _Base_ptr __x = _M_begin();\n+ _Base_ptr __y = _M_end();\n+ bool __comp = true;\n+ while (__x)\n+\t{\n+\t __y = __x;\n+\t __comp = _M_key_compare(__k, _S_key(__x));\n+\t __x = __comp ? _S_left(__x) : _S_right(__x);\n+\t}\n+ iterator __j = iterator(__y);\n+ if (__comp)\n+\t{\n+\t if (__j == begin())\n+\t return _Res(__x, __y);\n+\t else\n+\t --__j;\n+\t}\n+ if (_M_key_compare(_S_key(__j._M_node), __k))\n+\treturn _Res(__x, __y);\n+ return _Res(__j._M_node, _Base_ptr());\n+ }\n+\n template<typename _Key, typename _Val, typename _KeyOfValue,\n \t typename _Compare, typename _Alloc>\n pair<typename _Rb_tree<_Key, _Val, _KeyOfValue,\n@@ -2936,6 +2979,65 @@ namespace __rb_tree\n \treturn _Res(__position._M_node, _Base_ptr());\n }\n \n+ template<typename _Key, typename _Val, typename _KeyOfValue,\n+\t typename _Compare, typename _Alloc>\n+ template <typename _Kt>\n+ pair<\n+\ttypename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n+\t _Base_ptr,\n+\ttypename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n+\t _Base_ptr>\n+ _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::\n+ _M_get_insert_hint_unique_pos_tr(\n+\t const_iterator __position, const _Kt& __k)\n+ {\n+\ttypedef pair<_Base_ptr, _Base_ptr> _Res;\n+\n+\t// end()\n+\tif (__position._M_node == _M_end())\n+\t {\n+\t if (size() > 0 && _M_key_compare(_S_key(_M_rightmost()), __k))\n+\t return _Res(_Base_ptr(), _M_rightmost());\n+\t else\n+\t return _M_get_insert_unique_pos_tr(__k);\n+\t }\n+\telse if (_M_key_compare(__k, _S_key(__position._M_node)))\n+\t {\n+\t // First, try before...\n+\t iterator __before(__position._M_node);\n+\t if (__position._M_node == _M_leftmost()) // begin()\n+\t return _Res(_M_leftmost(), _M_leftmost());\n+\t else if (_M_key_compare(_S_key((--__before)._M_node), __k))\n+\t {\n+\t\tif (!_S_right(__before._M_node))\n+\t\t return _Res(_Base_ptr(), __before._M_node);\n+\t\telse\n+\t\t return _Res(__position._M_node, __position._M_node);\n+\t }\n+\t else\n+\t return _M_get_insert_unique_pos_tr(__k);\n+\t }\n+\telse if (_M_key_compare(_S_key(__position._M_node), __k))\n+\t {\n+\t // ... then try after.\n+\t iterator __after(__position._M_node);\n+\t if (__position._M_node == _M_rightmost())\n+\t return _Res(_Base_ptr(), _M_rightmost());\n+\t else if (_M_key_compare(__k, _S_key((++__after)._M_node)))\n+\t {\n+\t\tif (!_S_right(__position._M_node))\n+\t\t return _Res(_Base_ptr(), __position._M_node);\n+\t\telse\n+\t\t return _Res(__after._M_node, __after._M_node);\n+\t }\n+\t else\n+\t return _M_get_insert_unique_pos_tr(__k);\n+\t }\n+\telse\n+\t // Equivalent keys.\n+\t return _Res(__position._M_node, _Base_ptr());\n+ }\n+\n template<typename _Key, typename _Val, typename _KeyOfValue,\n \t typename _Compare, typename _Alloc>\n #if __cplusplus >= 201103L\n@@ -3155,7 +3257,7 @@ namespace __rb_tree\n \t return __z._M_insert(__res);\n \treturn __z._M_insert_equal_lower();\n }\n-#endif\n+#endif // >= C++11\n \n \n template<typename _Key, typename _Val, typename _KeyOfValue,\ndiff --git a/libstdc++-v3/include/bits/unordered_map.h b/libstdc++-v3/include/bits/unordered_map.h\nindex 9b74cba8675..1bd2906ace4 100644\n--- a/libstdc++-v3/include/bits/unordered_map.h\n+++ b/libstdc++-v3/include/bits/unordered_map.h\n@@ -456,6 +456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \templace(_Args&&... __args)\n \t{ return _M_h.emplace(std::forward<_Args>(__args)...); }\n \n+ ///@{\n /**\n * @brief Attempts to build and insert a std::pair into the\n * %unordered_map.\n@@ -520,6 +521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n #endif // node_extract\n \n #ifdef __glibcxx_unordered_map_try_emplace // C++ >= 17 && HOSTED\n+ ///@{\n /**\n * @brief Attempts to build and insert a std::pair into the\n * %unordered_map.\n@@ -558,6 +560,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t\t\t\t std::forward<_Args>(__args)...);\n \t}\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt, typename ..._Args>\n+\tpair<iterator, bool>\n+\ttry_emplace(_Kt&& __k, _Args&&... __args)\n+\t{\n+\t return _M_h.try_emplace(cend(),\n+\t std::forward<_Kt>(__k), std::forward<_Args>(__args)...);\n+\t}\n+#endif\n+ ///@}\n+\n+ ///@{\n /**\n * @brief Attempts to build and insert a std::pair into the\n * %unordered_map.\n@@ -605,6 +619,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t}\n #endif // __glibcxx_unordered_map_try_emplace\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt, typename ..._Args>\n+\titerator\n+\ttry_emplace(const_iterator __hint, _Kt&& __k, _Args&&... __args)\n+\t{\n+\t return _M_h.try_emplace(__hint,\n+\t std::forward<_Kt>(__k), std::forward<_Args>(__args)...).first;\n+\t}\n+#endif\n+ ///@}\n+\n ///@{\n /**\n * @brief Attempts to insert a std::pair into the %unordered_map.\n@@ -722,6 +747,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n #endif\n \n #ifdef __glibcxx_unordered_map_try_emplace // >= C++17 && HOSTED\n+ ///@{\n /**\n * @brief Attempts to insert a std::pair into the %unordered_map.\n * @param __k Key to use for finding a possibly existing pair in\n@@ -765,6 +791,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t return __ret;\n \t}\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt, typename _Obj>\n+\tpair<iterator, bool>\n+\tinsert_or_assign(_Kt&& __k, _Obj&& __obj)\n+\t{\n+\t auto __ret = _M_h.try_emplace(\n+\t cend(), std::forward<_Kt>(__k), std::forward<_Obj>(__obj));\n+\t if (!__ret.second)\n+\t __ret.first->second = std::forward<_Obj>(__obj);\n+\t return __ret;\n+\t}\n+#endif\n+ ///@}\n+\n+ ///@{\n /**\n * @brief Attempts to insert a std::pair into the %unordered_map.\n * @param __hint An iterator that serves as a hint as to where the\n@@ -813,6 +854,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n \t __ret.first->second = std::forward<_Obj>(__obj);\n \t return __ret.first;\n \t}\n+\n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt, typename _Obj>\n+\titerator\n+\tinsert_or_assign(const_iterator __hint, _Kt&& __k, _Obj&& __obj)\n+\t{\n+\t auto __ret = _M_h.try_emplace(__hint,\n+\t std::forward<_Kt>(__k), std::forward<_Obj>(__obj));\n+\t if (!__ret.second)\n+\t __ret.first->second = std::forward<_Obj>(__obj);\n+\t return __ret.first;\n+\t}\n+#endif\n+ ///@}\n #endif // unordered_map_try_emplace\n \n ///@{\n@@ -1089,6 +1144,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n mapped_type&\n operator[](key_type&& __k)\n { return _M_h[std::move(__k)]; }\n+\n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt>\n+\tmapped_type&\n+\toperator[](_Kt&& __k)\n+ {\n+\treturn try_emplace(std::forward<_Kt>(__k)).first->second;\n+ }\n+#endif\n ///@}\n \n ///@{\n@@ -1103,9 +1167,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n at(const key_type& __k)\n { return _M_h.at(__k); }\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt>\n+\tmapped_type&\n+\tat(const _Kt& __k)\n+\t{ return _M_h._M_at_tr(__k); }\n+#endif\n+\n const mapped_type&\n at(const key_type& __k) const\n { return _M_h.at(__k); }\n+\n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt>\n+\tconst mapped_type&\n+\tat(const _Kt& __k) const\n+\t{ return _M_h._M_at_tr(__k); }\n+#endif\n ///@}\n \n // bucket interface.\n@@ -1129,6 +1207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket_size(size_type __n) const\n { return _M_h.bucket_size(__n); }\n \n+ ///@{\n /*\n * @brief Returns the bucket index of a given element.\n * @param __key A key instance.\n@@ -1138,6 +1217,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket(const key_type& __key) const\n { return _M_h.bucket(__key); }\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_map> _Kt>\n+\tsize_type\n+\tbucket(const _Kt& __key) const\n+\t{ return _M_h._M_bucket_tr(__key); }\n+#endif\n+ ///@}\n+\n /**\n * @brief Returns a read/write iterator pointing to the first bucket\n * element.\n@@ -2176,6 +2263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket_size(size_type __n) const\n { return _M_h.bucket_size(__n); }\n \n+ ///@{\n /*\n * @brief Returns the bucket index of a given element.\n * @param __key A key instance.\n@@ -2185,6 +2273,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket(const key_type& __key) const\n { return _M_h.bucket(__key); }\n \n+#ifdef __glibcxx_associative_heterogeneous_insertion // C++26\n+ template <__heterogeneous_hash_key<unordered_multimap> _Kt>\n+\tsize_type\n+\tbucket(const _Kt& __key) const\n+\t{ return _M_h._M_bucket_tr(__key); }\n+#endif\n+ ///@}\n+\n /**\n * @brief Returns a read/write iterator pointing to the first bucket\n * element.\ndiff --git a/libstdc++-v3/include/bits/unordered_set.h b/libstdc++-v3/include/bits/unordered_set.h\nindex 22b2ad9caf4..044b49e6cd4 100644\n--- a/libstdc++-v3/include/bits/unordered_set.h\n+++ b/libstdc++-v3/include/bits/unordered_set.h\n@@ -493,6 +493,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n std::pair<iterator, bool>\n insert(value_type&& __x)\n { return _M_h.insert(std::move(__x)); }\n+\n+#if __glibcxx_associative_heterogeneous_insertion // P2363R5\n+ template <__heterogeneous_hash_key<unordered_set> _Kt>\n+\tstd::pair<iterator, bool>\n+\tinsert(_Kt&& __x)\n+\t{ return _M_h._M_insert_tr(std::forward<_Kt>(__x)); }\n+#endif\n ///@}\n \n ///@{\n@@ -522,6 +529,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n iterator\n insert(const_iterator __hint, value_type&& __x)\n { return _M_h.insert(__hint, std::move(__x)); }\n+\n+#if __glibcxx_associative_heterogeneous_insertion // P2363R5\n+ template <__heterogeneous_hash_key<unordered_set> _Kt>\n+\titerator\n+\tinsert(const_iterator, _Kt&& __x)\n+\t{ return _M_h._M_insert_tr(std::forward<_Kt>(__x)).first; }\n+#endif\n ///@}\n \n /**\n@@ -876,6 +890,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket_size(size_type __n) const\n { return _M_h.bucket_size(__n); }\n \n+ ///@{\n /*\n * @brief Returns the bucket index of a given element.\n * @param __key A key instance.\n@@ -885,6 +900,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket(const key_type& __key) const\n { return _M_h.bucket(__key); }\n \n+#if __glibcxx_associative_heterogeneous_insertion // P2363R5\n+ template <__heterogeneous_hash_key<unordered_set> _Kt>\n+\tsize_type\n+\tbucket(const _Kt& __key) const\n+\t{ return _M_h._M_bucket_tr(__key); }\n+#endif\n+ ///@}\n+\n ///@{\n /**\n * @brief Returns a read-only (constant) iterator pointing to the first\n@@ -1884,6 +1907,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket_size(size_type __n) const\n { return _M_h.bucket_size(__n); }\n \n+ ///@{\n /*\n * @brief Returns the bucket index of a given element.\n * @param __key A key instance.\n@@ -1893,6 +1917,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER\n bucket(const key_type& __key) const\n { return _M_h.bucket(__key); }\n \n+#if __glibcxx_associative_heterogeneous_insertion // P2363R5\n+ template <__heterogeneous_hash_key<unordered_multiset> _Kt>\n+\tsize_type\n+\tbucket(const _Kt& __key) const\n+\t{ return _M_h._M_bucket_tr(__key); }\n+#endif\n+ ///@}\n+\n ///@{\n /**\n * @brief Returns a read-only (constant) iterator pointing to the first\ndiff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def\nindex 4b8e9d43ec2..01725999c52 100644\n--- a/libstdc++-v3/include/bits/version.def\n+++ b/libstdc++-v3/include/bits/version.def\n@@ -1641,6 +1641,14 @@ ftms = {\n };\n };\n \n+ftms = {\n+ name = associative_heterogeneous_insertion;\n+ values = {\n+ v = 202306;\n+ cxxmin = 26;\n+ };\n+};\n+\n ftms = {\n name = is_scoped_enum;\n values = {\ndiff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h\nindex 7602225cb6d..b376c428ced 100644\n--- a/libstdc++-v3/include/bits/version.h\n+++ b/libstdc++-v3/include/bits/version.h\n@@ -1811,6 +1811,16 @@\n #endif /* !defined(__cpp_lib_associative_heterogeneous_erasure) */\n #undef __glibcxx_want_associative_heterogeneous_erasure\n \n+#if !defined(__cpp_lib_associative_heterogeneous_insertion)\n+# if (__cplusplus > 202302L)\n+# define __glibcxx_associative_heterogeneous_insertion 202306L\n+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_associative_heterogeneous_insertion)\n+# define __cpp_lib_associative_heterogeneous_insertion 202306L\n+# endif\n+# endif\n+#endif /* !defined(__cpp_lib_associative_heterogeneous_insertion) */\n+#undef __glibcxx_want_associative_heterogeneous_insertion\n+\n #if !defined(__cpp_lib_is_scoped_enum)\n # if (__cplusplus >= 202100L)\n # define __glibcxx_is_scoped_enum 202011L\ndiff --git a/libstdc++-v3/include/std/map b/libstdc++-v3/include/std/map\nindex 91612cf42c4..66edadbc6dc 100644\n--- a/libstdc++-v3/include/std/map\n+++ b/libstdc++-v3/include/std/map\n@@ -80,6 +80,7 @@\n #define __glibcxx_want_nonmember_container_access\n #define __glibcxx_want_tuple_like\n #define __glibcxx_want_associative_heterogeneous_erasure\n+#define __glibcxx_want_associative_heterogeneous_insertion\n #include <bits/version.h>\n \n #if __cplusplus >= 201703L\ndiff --git a/libstdc++-v3/include/std/set b/libstdc++-v3/include/std/set\nindex 28eef1fc490..dc550f1d0b6 100644\n--- a/libstdc++-v3/include/std/set\n+++ b/libstdc++-v3/include/std/set\n@@ -78,6 +78,7 @@\n #define __glibcxx_want_node_extract\n #define __glibcxx_want_nonmember_container_access\n #define __glibcxx_want_associative_heterogeneous_erasure\n+#define __glibcxx_want_associative_heterogeneous_insertion\n #include <bits/version.h>\n \n #if __cplusplus >= 201703L\ndiff --git a/libstdc++-v3/include/std/unordered_map b/libstdc++-v3/include/std/unordered_map\nindex f63be4104c5..e9cf191e749 100644\n--- a/libstdc++-v3/include/std/unordered_map\n+++ b/libstdc++-v3/include/std/unordered_map\n@@ -57,6 +57,7 @@\n #define __glibcxx_want_unordered_map_try_emplace\n #define __glibcxx_want_tuple_like\n #define __glibcxx_want_associative_heterogeneous_erasure\n+#define __glibcxx_want_associative_heterogeneous_insertion\n #include <bits/version.h>\n \n #if __cplusplus >= 201703L\ndiff --git a/libstdc++-v3/include/std/unordered_set b/libstdc++-v3/include/std/unordered_set\nindex 45e6a915eb9..ee16489290e 100644\n--- a/libstdc++-v3/include/std/unordered_set\n+++ b/libstdc++-v3/include/std/unordered_set\n@@ -55,6 +55,7 @@\n #define __glibcxx_want_node_extract\n #define __glibcxx_want_nonmember_container_access\n #define __glibcxx_want_associative_heterogeneous_erasure\n+#define __glibcxx_want_associative_heterogeneous_insertion\n #include <bits/version.h>\n \n #if __cplusplus >= 201703L\ndiff --git a/libstdc++-v3/testsuite/23_containers/map/modifiers/hetero/insert.cc b/libstdc++-v3/testsuite/23_containers/map/modifiers/hetero/insert.cc\nnew file mode 100644\nindex 00000000000..73db5d28b26\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/map/modifiers/hetero/insert.cc\n@@ -0,0 +1,341 @@\n+// { dg-do run { target c++26 } }\n+\n+#include <map>\n+#include <string>\n+#include <string_view>\n+#include <utility>\n+#include <compare>\n+#include <cstring>\n+#include <testsuite_hooks.h>\n+\n+struct Y;\n+\n+struct X {\n+ std::string s;\n+ X(std::string_view str) : s(str) {}\n+ X(Y&& y);\n+ X(const Y& y);\n+ friend auto operator<=>(X const& a, X const& b) = default;\n+};\n+\n+struct Y {\n+ std::string s;\n+ Y() = default;\n+ Y(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+ Y(const Y& y) = default;\n+ Y& operator=(Y&& y) { s = std::move(y.s); y.s.clear(); return *this; }\n+ Y& operator=(const Y& y) = default;\n+ Y(std::string_view sv) : s(sv) {}\n+ Y(int n) : s(std::string('a', n)) {}\n+ Y(const Y& a, const Y& b) : s(a.s + \"1\" + b.s) { }\n+ Y(const Y& a, Y&& b) : s(a.s + \"2\" + b.s) { b.s.clear(); }\n+ Y(Y&& a, const Y& b) : s(a.s + \"3\" + b.s) { a.s.clear(); }\n+ Y(Y&& a, Y&& b) : s(a.s + \"4\" + b.s) { a.s.clear(), b.s.clear(); }\n+ friend auto operator<=>(Y const& a, Y const& b) = default;\n+ friend auto operator<=>(X const& a, Y const& b) { return a.s <=> b.s; }\n+};\n+\n+X::X(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+X::X(const Y& y) : s(y.s) {}\n+\n+using cmp = std::less<void>;\n+\n+void test1() // op[]\n+{\n+ std::map<X, Y, cmp> amap{cmp{}};\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+ Y x{\"dei\"}, y{\"deh\"}, z{\"deg\"};\n+ amap[z] = 4;\n+ VERIFY(amap.size() == 4);\n+ VERIFY(z.s.size() == 3); // not moved from.\n+\n+ amap[std::move(z)] = 5;\n+ VERIFY(amap.size() == 4);\n+ VERIFY(z.s.size() == 3); // not moved from.\n+\n+ VERIFY(amap[std::move(y)] == Y{});\n+ VERIFY(amap.size() == 5);\n+ VERIFY(y.s.empty()); // moved from.\n+\n+ amap[std::move(x)] = 7;\n+ VERIFY(amap.size() == 6);\n+ VERIFY(x.s.empty()); // moved from\n+}\n+\n+void test2() // at()\n+{\n+ std::map<X, Y, cmp> amap{cmp{}};\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ Y y{\"def\"};\n+ try\n+ {\n+ VERIFY(2 == amap.at(y));\n+ VERIFY(amap.size() == 3);\n+ VERIFY(4 == (amap.at(std::move(y)) = 4));\n+ VERIFY(amap.size() == 3);\n+ VERIFY(y.s.size() == 3); // not moved from\n+ }\n+ catch(...) { VERIFY(false); }\n+ try\n+ {\n+ amap.at(Y{\"deg\"}) = 4;\n+ VERIFY(false); // Should have thrown.\n+ }\n+ catch (std::out_of_range&) { VERIFY(amap.size() == 3); }\n+ catch (...) { VERIFY(false); } // Wrong exception.\n+\n+ auto const& amapr{amap};\n+ Y z{\"deh\"};\n+ try\n+ {\n+ amapr.at(std::move(z));\n+ VERIFY(false); // Should have thrown.\n+ }\n+ catch (std::out_of_range&) { }\n+ catch (...) { VERIFY(false); } // Wrong exception.\n+ VERIFY(amapr.size() == 3);\n+ VERIFY(z.s.size() == 3); // not moved from\n+}\n+\n+void test3() // try_emplace\n+{\n+ std::map<X, Y, cmp> amap{cmp{}};\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ { // Fail, already there\n+ auto a = amap;\n+ auto [it, res] = a.try_emplace(Y{\"def\"}, Y{\"xyz\"});\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{2});\n+ }\n+ { // Fail, already there, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto [it, res] = a.try_emplace(std::move(y), std::move(z));\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{2});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Succeed, construct\n+ auto a = amap;\n+ Y m(\"m\"), n(\"n\"), o(\"o\"), p(\"p\"), dek(\"dek\");\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"deg\"}, m, n);\n+ VERIFY(res);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->first == X{\"deg\"});\n+ VERIFY(it->second == Y{\"m1n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.size() == 1);\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"deh\"}, m, std::move(n));\n+ VERIFY(res);\n+ VERIFY(a.size() == 5);\n+ VERIFY(it->first == X{\"deh\"});\n+ VERIFY(it->second == Y{\"m2n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.empty());\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"dei\"}, std::move(m), o);\n+ VERIFY(res);\n+ VERIFY(a.size() == 6);\n+ VERIFY(it->first == X{\"dei\"});\n+ VERIFY(it->second == Y{\"m3o\"});\n+ VERIFY(m.s.empty());\n+ VERIFY(o.s.size() == 1);\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"dej\"}, std::move(o), std::move(p));\n+ VERIFY(res);\n+ VERIFY(a.size() == 7);\n+ VERIFY(it->first == X{\"dej\"});\n+ VERIFY(it->second == Y{\"o4p\"});\n+ VERIFY(o.s.empty());\n+ VERIFY(p.s.empty());\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(std::move(dek), Y(\"q\"), Y(\"r\"));\n+ VERIFY(res);\n+ VERIFY(a.size() == 8);\n+ VERIFY(dek.s.empty());\n+ VERIFY(it->first == X{\"dek\"});\n+ VERIFY(it->second == Y{\"q4r\"});\n+ }\n+ }\n+ { // Succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto [it, res] = a.try_emplace(std::move(y), std::move(z));\n+ VERIFY(res);\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Hinted, fail\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.try_emplace(a.begin(), std::move(y), std::move(z));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{2});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, fail, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.try_emplace(a.begin(), std::move(y), std::move(z));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{2});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, succeed, construct\n+ auto a = amap;\n+ Y m(\"m\"), n(\"n\"), o(\"o\"), p(\"p\"), dek(\"dek\");\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"deg\"}, m, n);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->first == X{\"deg\"});\n+ VERIFY(it->second == Y{\"m1n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.size() == 1);\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"deh\"}, m, std::move(n));\n+ VERIFY(a.size() == 5);\n+ VERIFY(it->first == X{\"deh\"});\n+ VERIFY(it->second == Y{\"m2n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.empty());\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"dei\"}, std::move(m), o);\n+ VERIFY(a.size() == 6);\n+ VERIFY(it->first == X{\"dei\"});\n+ VERIFY(it->second == Y{\"m3o\"});\n+ VERIFY(m.s.empty());\n+ VERIFY(o.s.size() == 1);\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"dej\"}, std::move(o), std::move(p));\n+ VERIFY(a.size() == 7);\n+ VERIFY(it->first == X{\"dej\"});\n+ VERIFY(it->second == Y{\"o4p\"});\n+ VERIFY(o.s.empty());\n+ VERIFY(p.s.empty());\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), std::move(dek), Y(\"q\"), Y(\"r\"));\n+ VERIFY(a.size() == 8);\n+ VERIFY(dek.s.empty());\n+ VERIFY(it->first == X{\"dek\"});\n+ VERIFY(it->second == Y{\"q4r\"});\n+ }\n+ }\n+ { // Hinted, succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto it = a.try_emplace(a.begin(), std::move(y), std::move(z));\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+}\n+\n+void test4() // insert_or_assign\n+{\n+ std::map<X, Y, cmp> amap{cmp{}};\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ { // Already there, replace\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto [it, res] = a.insert_or_assign(y, z);\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Already there, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto [it, res] = a.insert_or_assign(std::move(y), std::move(z));\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto [it, res] = a.insert_or_assign(std::move(y), std::move(z));\n+ VERIFY(res);\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Hinted, already there, replace\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), y, z);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, already there, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), std::move(y), std::move(z));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Hinted, succeed\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), y, z);\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), std::move(y), std::move(z));\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+}\n+\n+int main()\n+{\n+ test1();\n+ test2();\n+ test3();\n+ test4();\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/set/modifiers/hetero/insert.cc b/libstdc++-v3/testsuite/23_containers/set/modifiers/hetero/insert.cc\nnew file mode 100644\nindex 00000000000..ac13b514778\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/set/modifiers/hetero/insert.cc\n@@ -0,0 +1,120 @@\n+// { dg-do run { target c++26 } }\n+\n+#include <set>\n+#include <string>\n+#include <string_view>\n+#include <utility>\n+#include <compare>\n+#include <cstring>\n+#include <testsuite_hooks.h>\n+\n+struct Y;\n+\n+struct X {\n+ std::string s;\n+ X(std::string_view str) : s(str) {}\n+ X(Y&& y);\n+ X(const Y& y);\n+\n+ friend auto operator<=>(X const& a, X const& b) = default;\n+};\n+\n+struct Y {\n+ std::string s;\n+ Y() = default;\n+ Y(std::string_view sv) : s(sv) {}\n+ Y(int a, int b = 0) : s(std::string('a', a + b)) {}\n+ Y(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+ Y(const Y& y) = default;\n+ Y& operator=(Y&& y) { s = std::move(y.s); y.s.clear(); return *this; }\n+ Y& operator=(const Y& y) = default;\n+ friend auto operator<=>(Y const& a, Y const& b) = default;\n+ friend auto operator<=>(X const& a, Y const& b) { return a.s <=> b.s; }\n+};\n+\n+X::X(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+X::X(const Y& y) : s(y.s) {}\n+\n+using cmp = std::less<void>;\n+\n+void test1() // insert\n+{\n+ std::set<X, cmp> aset{cmp{}};\n+ aset.insert({X{\"abc\"}, X{\"def\"}, X{\"ghi\"}});\n+\n+ { // Fail\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto [it, res] = a.insert(y);\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Fail, move\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto [it, res] = a.insert(std::move(y));\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Succeed\n+ auto a = aset;\n+ Y y{\"deg\"};\n+ auto [it, res] = a.insert(y);\n+ VERIFY(res);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deg\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Succeed, move\n+ auto a = aset;\n+ Y y{\"deg\"};\n+ auto [it, res] = a.insert(std::move(y));\n+ VERIFY(res);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deg\");\n+ VERIFY(y.s.empty()); // moved\n+ }\n+\n+\n+ { // Hinted, fail\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto it = a.insert(a.begin(), y);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Hinted, fail, move\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto it = a.insert(a.begin(), std::move(y));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Hinted, succeed\n+ auto a = aset;\n+ Y y{\"deh\"};\n+ auto it = a.insert(a.begin(), y);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deh\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Hinted, succeed, move\n+ auto a = aset;\n+ Y y{\"deh\"};\n+ auto it = a.insert(a.begin(), std::move(y));\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deh\");\n+ VERIFY(y.s.empty()); // moved\n+ }\n+}\n+\n+int main()\n+{\n+ test1();\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/hetero/insert.cc b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/hetero/insert.cc\nnew file mode 100644\nindex 00000000000..8f7f88ce9e1\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_map/modifiers/hetero/insert.cc\n@@ -0,0 +1,353 @@\n+// { dg-do run { target c++26 } }\n+\n+#include <unordered_map>\n+#include <string>\n+#include <string_view>\n+#include <utility>\n+#include <functional>\n+#include <compare>\n+#include <testsuite_hooks.h>\n+\n+struct Y;\n+\n+struct X {\n+ std::string s;\n+ X(std::string_view str) : s(str) {}\n+ X(Y&& y);\n+ X(const Y& y);\n+ friend bool operator==(X const& a, X const& b) = default;\n+};\n+\n+struct Y {\n+ std::string s;\n+ Y() = default;\n+ Y(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+ Y(const Y& y) = default;\n+ Y& operator=(Y&& y) { s = std::move(y.s); y.s.clear(); return *this; }\n+ Y& operator=(const Y& y) = default;\n+ Y(std::string_view sv) : s(sv) {}\n+ Y(int n) : s(std::string('a', n)) {}\n+ Y(const Y& a, const Y& b) : s(a.s + \"1\" + b.s) { }\n+ Y(const Y& a, Y&& b) : s(a.s + \"2\" + b.s) { b.s.clear(); }\n+ Y(Y&& a, const Y& b) : s(a.s + \"3\" + b.s) { a.s.clear(); }\n+ Y(Y&& a, Y&& b) : s(a.s + \"4\" + b.s) { a.s.clear(), b.s.clear(); }\n+ friend bool operator==(Y const& a, Y const& b) = default;\n+ friend bool operator==(X const& a, Y const& b) { return a.s == b.s; }\n+};\n+\n+X::X(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+X::X(const Y& y) : s(y.s) {}\n+\n+struct Hash {\n+ using is_transparent = void;\n+ template <typename T>\n+ auto operator()(T const& t) const\n+ { return std::hash<decltype(T::s)>{}(t.s); }\n+};\n+\n+using Equal = std::equal_to<void>;\n+\n+void test1() // op[]\n+{\n+ std::unordered_map<X, Y, Hash, Equal> amap;\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ Y x{\"dei\"}, y{\"deh\"}, z{\"deg\"};\n+ amap[z] = 4;\n+ VERIFY(amap.size() == 4);\n+ VERIFY(z.s.size() == 3); // not moved from.\n+\n+ amap[std::move(z)] = 5;\n+ VERIFY(amap.size() == 4);\n+ VERIFY(z.s.size() == 3); // not moved from.\n+\n+ VERIFY(amap[std::move(y)] == Y{});\n+ VERIFY(amap.size() == 5);\n+ VERIFY(y.s.empty()); // moved from.\n+\n+ amap[std::move(x)] = 7;\n+ VERIFY(amap.size() == 6);\n+ VERIFY(x.s.empty()); // moved from\n+}\n+\n+void test2() // at()\n+{\n+ std::unordered_map<X, Y, Hash, Equal> amap;\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ Y x{\"def\"};\n+ try\n+ {\n+ VERIFY(2 == amap.at(x));\n+ VERIFY(amap.size() == 3);\n+ VERIFY(x.s.size() == 3); // not moved from\n+ VERIFY(4 == (amap.at(x) = 4));\n+ VERIFY(amap.size() == 3);\n+ VERIFY(x.s.size() == 3); // not moved from\n+ }\n+ catch(...) { VERIFY(false); }\n+\n+ Y z{\"deg\"};\n+ try\n+ {\n+ amap.at(z) = 4;\n+ VERIFY(false); // Should have thrown.\n+ }\n+ catch (std::out_of_range&) { VERIFY(amap.size() == 3); }\n+ catch (...) { VERIFY(false); } // Wrong exception.\n+ VERIFY(z.s.size() == 3); // not moved from\n+\n+ Y y{\"deh\"};\n+ auto const& amapr{amap};\n+ try\n+ {\n+ amapr.at(y);\n+ VERIFY(false); // Should have thrown.\n+ }\n+ catch (std::out_of_range&) { }\n+ catch (...) { VERIFY(false); } // Wrong exception.\n+ VERIFY(amapr.size() == 3);\n+ VERIFY(y.s.size() == 3); // not moved from\n+}\n+\n+void test3() // try_emplace\n+{\n+ std::unordered_map<X, Y, Hash, Equal> amap;\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ { // Fail, already there\n+ auto a = amap;\n+ auto [it, res] = a.try_emplace(Y{\"def\"}, Y{\"xyz\"});\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{2});\n+ }\n+ { // Fail, already there, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto [it, res] = a.try_emplace(std::move(y), std::move(z));\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{2});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Succeed, construct\n+ auto a = amap;\n+ Y m(\"m\"), n(\"n\"), o(\"o\"), p(\"p\"), dek(\"dek\");\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"deg\"}, m, n);\n+ VERIFY(res);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->first == X{\"deg\"});\n+ VERIFY(it->second == Y{\"m1n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.size() == 1);\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"deh\"}, m, std::move(n));\n+ VERIFY(res);\n+ VERIFY(a.size() == 5);\n+ VERIFY(it->first == X{\"deh\"});\n+ VERIFY(it->second == Y{\"m2n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.empty());\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"dei\"}, std::move(m), o);\n+ VERIFY(res);\n+ VERIFY(a.size() == 6);\n+ VERIFY(it->first == X{\"dei\"});\n+ VERIFY(it->second == Y{\"m3o\"});\n+ VERIFY(m.s.empty());\n+ VERIFY(o.s.size() == 1);\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(Y{\"dej\"}, std::move(o), std::move(p));\n+ VERIFY(res);\n+ VERIFY(a.size() == 7);\n+ VERIFY(it->first == X{\"dej\"});\n+ VERIFY(it->second == Y{\"o4p\"});\n+ VERIFY(o.s.empty());\n+ VERIFY(p.s.empty());\n+ }\n+ {\n+ auto [it, res] = a.try_emplace(std::move(dek), Y(\"q\"), Y(\"r\"));\n+ VERIFY(res);\n+ VERIFY(a.size() == 8);\n+ VERIFY(dek.s.empty());\n+ VERIFY(it->first == X{\"dek\"});\n+ VERIFY(it->second == Y{\"q4r\"});\n+ }\n+ }\n+ { // Succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto [it, res] = a.try_emplace(std::move(y), std::move(z));\n+ VERIFY(res);\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Hinted, fail\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.try_emplace(a.begin(), std::move(y), std::move(z));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{2});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, fail, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.try_emplace(a.begin(), std::move(y), std::move(z));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{2});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, succeed, construct\n+ auto a = amap;\n+ Y m(\"m\"), n(\"n\"), o(\"o\"), p(\"p\"), dek(\"dek\");\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"deg\"}, m, n);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->first == X{\"deg\"});\n+ VERIFY(it->second == Y{\"m1n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.size() == 1);\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"deh\"}, m, std::move(n));\n+ VERIFY(a.size() == 5);\n+ VERIFY(it->first == X{\"deh\"});\n+ VERIFY(it->second == Y{\"m2n\"});\n+ VERIFY(m.s.size() == 1);\n+ VERIFY(n.s.empty());\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"dei\"}, std::move(m), o);\n+ VERIFY(a.size() == 6);\n+ VERIFY(it->first == X{\"dei\"});\n+ VERIFY(it->second == Y{\"m3o\"});\n+ VERIFY(m.s.empty());\n+ VERIFY(o.s.size() == 1);\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), Y{\"dej\"}, std::move(o), std::move(p));\n+ VERIFY(a.size() == 7);\n+ VERIFY(it->first == X{\"dej\"});\n+ VERIFY(it->second == Y{\"o4p\"});\n+ VERIFY(o.s.empty());\n+ VERIFY(p.s.empty());\n+ }\n+ {\n+ auto it = a.try_emplace(a.begin(), std::move(dek), Y(\"q\"), Y(\"r\"));\n+ VERIFY(a.size() == 8);\n+ VERIFY(dek.s.empty());\n+ VERIFY(it->first == X{\"dek\"});\n+ VERIFY(it->second == Y{\"q4r\"});\n+ }\n+ }\n+ { // Hinted, succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto it = a.try_emplace(a.begin(), std::move(y), std::move(z));\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+}\n+\n+void test4() // insert_or_assign\n+{\n+ std::unordered_map<X, Y, Hash, Equal> amap;\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"ghi\"}, 3}});\n+\n+ { // Already there, replace\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto [it, res] = a.insert_or_assign(y, z);\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Already there, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto [it, res] = a.insert_or_assign(std::move(y), std::move(z));\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(a.at(Y{\"def\"}) == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto [it, res] = a.insert_or_assign(std::move(y), std::move(z));\n+ VERIFY(res);\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Hinted, already there, replace\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), y, z);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, already there, move\n+ auto a = amap;\n+ Y y{\"def\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), std::move(y), std::move(z));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->first == X{\"def\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+ { // Hinted, succeed\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), y, z);\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.size() == 3); // not moved from\n+ VERIFY(z.s.size() == 3); // not moved from\n+ }\n+ { // Hinted, succeed, move\n+ auto a = amap;\n+ Y y{\"tuv\"}, z{\"xyz\"};\n+ auto it = a.insert_or_assign(a.begin(), std::move(y), std::move(z));\n+ VERIFY(it->first == X{\"tuv\"});\n+ VERIFY(it->second == Y{\"xyz\"});\n+ VERIFY(a.size() == 4);\n+ VERIFY(y.s.empty()); // moved from\n+ VERIFY(z.s.empty()); // moved from\n+ }\n+}\n+\n+int main()\n+{\n+ test1();\n+ test2();\n+ test3();\n+ test4();\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_multimap/modifiers/hetero/insert.cc b/libstdc++-v3/testsuite/23_containers/unordered_multimap/modifiers/hetero/insert.cc\nnew file mode 100644\nindex 00000000000..6430201c9c6\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_multimap/modifiers/hetero/insert.cc\n@@ -0,0 +1,57 @@\n+// { dg-do run { target c++26 } }\n+\n+#include <unordered_map>\n+#include <string>\n+#include <string_view>\n+#include <utility>\n+#include <functional>\n+#include <testsuite_hooks.h>\n+\n+struct Y;\n+\n+struct X {\n+ std::string s;\n+ X(std::string_view str) : s(str) {}\n+ X(Y&& y);\n+ X(const Y& y);\n+ friend bool operator==(X const& a, X const& b) = default;\n+};\n+\n+struct Y {\n+ std::string s;\n+ Y() = default;\n+ Y(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+ Y(const Y& y) = default;\n+ Y& operator=(Y&& y) { s = std::move(y.s); y.s.clear(); return *this; }\n+ Y& operator=(const Y& y) = default;\n+ Y(std::string_view sv) : s(sv) {}\n+ Y(int a, int b = 0) : s(std::string('a', a + b)) {}\n+ friend bool operator==(Y const& a, Y const& b) = default;\n+ friend bool operator==(X const& a, Y const& b) { return a.s == b.s; }\n+};\n+\n+X::X(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+X::X(const Y& y) : s(y.s) {}\n+\n+struct Hash {\n+ using is_transparent = void;\n+ template <typename T>\n+ auto operator()(T const& t) const\n+ { return std::hash<decltype(T::s)>{}(t.s); }\n+};\n+\n+using Equal = std::equal_to<void>;\n+\n+void test1() // bucket\n+{\n+ std::unordered_multimap<X, Y, Hash, Equal> amap;\n+ amap.insert({{X{\"abc\"}, 1}, {X{\"def\"}, 2}, {X{\"def\"}, 3}, {X{\"ghi\"}, 3}});\n+\n+ auto const& amapr{amap};\n+ VERIFY(amapr.bucket(X{\"def\"}) == amapr.bucket(Y{\"def\"}));\n+}\n+\n+int main()\n+{\n+ test1();\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_multiset/modifiers/hetero/insert.cc b/libstdc++-v3/testsuite/23_containers/unordered_multiset/modifiers/hetero/insert.cc\nnew file mode 100644\nindex 00000000000..59ed43c16d2\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_multiset/modifiers/hetero/insert.cc\n@@ -0,0 +1,56 @@\n+// { dg-do run { target c++26 } }\n+\n+#include <unordered_set>\n+#include <string>\n+#include <string_view>\n+#include <utility>\n+#include <functional>\n+#include <testsuite_hooks.h>\n+\n+struct Y;\n+\n+struct X {\n+ std::string s;\n+ X(Y&& y);\n+ X(const Y& y);\n+ X(std::string_view str) : s(str) {}\n+ friend bool operator==(X const& a, X const& b) = default;\n+};\n+\n+struct Y {\n+ std::string s;\n+ Y() = default;\n+ Y(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+ Y(const Y& y) = default;\n+ Y& operator=(Y&& y) { s = std::move(y.s); y.s.clear(); return *this; }\n+ Y& operator=(const Y& y) = default;\n+ Y(std::string_view sv) : s(sv) {}\n+ friend bool operator==(Y const& a, Y const& b) = default;\n+ friend bool operator==(X const& a, Y const& b) { return a.s == b.s; }\n+};\n+\n+X::X(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+X::X(const Y& y) : s(y.s) {}\n+\n+struct Hash {\n+ using is_transparent = void;\n+ template <typename T>\n+ auto operator()(T const& t) const\n+ { return std::hash<decltype(T::s)>{}(t.s); }\n+};\n+\n+using Equal = std::equal_to<void>;\n+\n+void test1() // bucket\n+{\n+ std::unordered_multiset<X, Hash, Equal> aset{};\n+ aset.insert({X{\"abc\"}, X{\"def\"}, X{\"def\"}, X{\"ghi\"}});\n+\n+ auto const& asetr{aset};\n+ VERIFY(asetr.bucket(X{\"def\"}) == asetr.bucket(Y{\"def\"}));\n+}\n+\n+int main()\n+{\n+ test1();\n+}\ndiff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/hetero/insert.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/hetero/insert.cc\nnew file mode 100644\nindex 00000000000..320143f2ea4\n--- /dev/null\n+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/modifiers/hetero/insert.cc\n@@ -0,0 +1,134 @@\n+// { dg-do run { target c++26 } }\n+\n+#include <unordered_set>\n+#include <string>\n+#include <string_view>\n+#include <utility>\n+#include <functional>\n+#include <testsuite_hooks.h>\n+\n+struct Y;\n+\n+struct X {\n+ std::string s;\n+ X(std::string_view str) : s(str) {}\n+ X(Y&& y);\n+ X(const Y& y);\n+ friend bool operator==(X const& a, X const& b) = default;\n+};\n+\n+struct Y {\n+ std::string s;\n+ Y() = default;\n+ Y(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+ Y(const Y& y) = default;\n+ Y& operator=(Y&& y) { s = std::move(y.s); y.s.clear(); return *this; }\n+ Y& operator=(const Y& y) = default;\n+ Y(int a, int b = 0) : s(std::string('a', a + b)) {}\n+ Y(std::string_view sv) : s(sv) {}\n+ friend bool operator==(Y const& a, Y const& b) = default;\n+ friend bool operator==(X const& a, Y const& b) { return a.s == b.s; }\n+};\n+\n+X::X(Y&& y) : s(std::move(y.s)) { y.s.clear(); }\n+X::X(const Y& y) : s(y.s) {}\n+\n+struct Hash {\n+ using is_transparent = void;\n+ template <typename T>\n+ auto operator()(T const& t) const { return std::hash<decltype(T::s)>{}(t.s); }\n+};\n+\n+using Equal = std::equal_to<void>;\n+\n+void test1() // insert\n+{\n+ std::unordered_set<X, Hash, Equal> aset;\n+ aset.insert({X{\"abc\"}, X{\"def\"}, X{\"ghi\"}});\n+\n+ { // Fail\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto [it, res] = a.insert(y);\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Fail, move\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto [it, res] = a.insert(std::move(y));\n+ VERIFY(!res);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Succeed\n+ auto a = aset;\n+ Y y{\"deg\"};\n+ auto [it, res] = a.insert(y);\n+ VERIFY(res);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deg\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Succeed, move\n+ auto a = aset;\n+ Y y{\"deg\"};\n+ auto [it, res] = a.insert(std::move(y));\n+ VERIFY(res);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deg\");\n+ VERIFY(y.s.empty()); // moved\n+ }\n+\n+\n+ { // Hinted, fail\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto it = a.insert(a.begin(), y);\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Hinted, fail, move\n+ auto a = aset;\n+ Y y{\"def\"};\n+ auto it = a.insert(a.begin(), std::move(y));\n+ VERIFY(a.size() == 3);\n+ VERIFY(it->s == \"def\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Hinted, succeed\n+ auto a = aset;\n+ Y y{\"deh\"};\n+ auto it = a.insert(a.begin(), y);\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deh\");\n+ VERIFY(y.s.size() == 3); // not moved\n+ }\n+ { // Hinted, succeed, move\n+ auto a = aset;\n+ Y y{\"deh\"};\n+ auto it = a.insert(a.begin(), std::move(y));\n+ VERIFY(a.size() == 4);\n+ VERIFY(it->s == \"deh\");\n+ VERIFY(y.s.empty()); // moved\n+ }\n+}\n+\n+void test2() // bucket\n+{\n+ std::unordered_set<X, Hash, Equal> aset{};\n+ aset.insert({X{\"abc\"}, X{\"def\"}, X{\"ghi\"}});\n+\n+ auto const& asetr{aset};\n+ VERIFY(asetr.bucket(X{\"def\"}) == asetr.bucket(Y{\"def\"}));\n+}\n+\n+int main()\n+{\n+ test1();\n+ test2();\n+}\n", "prefixes": [ "PATCHv6" ] }