diff --git a/doc/modules/ROOT/nav_zh_Hans.adoc b/doc/modules/ROOT/nav_zh_Hans.adoc
new file mode 100644
index 0000000..2221eb9
--- /dev/null
+++ b/doc/modules/ROOT/nav_zh_Hans.adoc
@@ -0,0 +1,51 @@
+* xref:intro.adoc[]
+* xref:buckets.adoc[]
+* xref:hash_equality.adoc[]
+* xref:regular.adoc[]
+* xref:concurrent.adoc[]
+* xref:hash_quality.adoc[]
+* xref:compliance.adoc[合规性]
+* xref:structures.adoc[结构]
+* xref:debuggability.adoc[可调试性]
+* xref:benchmarks.adoc[基准测试]
+* xref:rationale.adoc[设计依据]
+* xref:ref.adoc[参考文档]
+** xref:reference/header_unordered_map_fwd.adoc[``]
+** xref:reference/header_unordered_map_top.adoc[``]
+** xref:reference/header_unordered_map.adoc[``]
+** xref:reference/unordered_map.adoc[`unordered_map`]
+** xref:reference/unordered_multimap.adoc[`unordered_multimap`]
+** xref:reference/header_unordered_set_fwd.adoc[``]
+** xref:reference/header_unordered_set_top.adoc[``]
+** xref:reference/header_unordered_set.adoc[``]
+** xref:reference/unordered_set.adoc[`unordered_set`]
+** xref:reference/unordered_multiset.adoc[`unordered_multiset`]
+** xref:reference/hash_traits.adoc[哈希特征]
+** xref:reference/stats.adoc[统计信息]
+** xref:reference/header_unordered_flat_map_fwd.adoc[``]
+** xref:reference/header_unordered_flat_map.adoc[``]
+** xref:reference/unordered_flat_map.adoc[`unordered_flat_map`]
+** xref:reference/header_unordered_flat_set_fwd.adoc[``]
+** xref:reference/header_unordered_flat_set.adoc[``]
+** xref:reference/unordered_flat_set.adoc[`unordered_flat_set`]
+** xref:reference/header_unordered_node_map_fwd.adoc[``]
+** xref:reference/header_unordered_node_map.adoc[``]
+** xref:reference/unordered_node_map.adoc[`unordered_node_map`]
+** xref:reference/header_unordered_node_set_fwd.adoc[``]
+** xref:reference/header_unordered_node_set.adoc[``]
+** xref:reference/unordered_node_set.adoc[`unordered_node_set`]
+** xref:reference/header_concurrent_flat_map_fwd.adoc[``]
+** xref:reference/header_concurrent_flat_map.adoc[``]
+** xref:reference/concurrent_flat_map.adoc[`concurrent_flat_map`]
+** xref:reference/header_concurrent_flat_set_fwd.adoc[``]
+** xref:reference/header_concurrent_flat_set.adoc[``]
+** xref:reference/concurrent_flat_set.adoc[`concurrent_flat_set`]
+** xref:reference/header_concurrent_node_map_fwd.adoc[``]
+** xref:reference/header_concurrent_node_map.adoc[``]
+** xref:reference/concurrent_node_map.adoc[`concurrent_node_map`]
+** xref:reference/header_concurrent_node_set_fwd.adoc[``]
+** xref:reference/header_concurrent_node_set.adoc[``]
+** xref:reference/concurrent_node_set.adoc[`concurrent_node_set`]
+* xref:changes.adoc[变更记录]
+* xref:bibliography.adoc[参考文献]
+* xref:copyright.adoc[版权声明]
diff --git a/doc/modules/ROOT/pages/benchmarks_zh_Hans.adoc b/doc/modules/ROOT/pages/benchmarks_zh_Hans.adoc
new file mode 100644
index 0000000..a6cca2f
--- /dev/null
+++ b/doc/modules/ROOT/pages/benchmarks_zh_Hans.adoc
@@ -0,0 +1,553 @@
+[#benchmarks]
+:idprefix: benchmarks_
+
+= 基准测试
+
+== boost::unordered_[multi]set
+
+所有基准测试均使用 `unordered++_++set++<++unsigned int++>++`(非重复元素) 和 `unordered++_++multiset++<++unsigned int++>++` (重复元素)创建。源代码可 https://github.com/boostorg/boost_unordered_benchmarks/tree/boost_unordered_set[在此处获取] 。
+
+插入基准测试会插入 `n` 个随机值,其中 `n` 的范围在10,000至300万之间。在重复值测试场景中,同一组随机值会平均重复插入 5 次。
+
+在擦除基准测试中,随机删除所有 `n` 个元素直至容器为空。通过键擦除操作使用 `erase(const key++_++type&)` 方法,每次调用将移除整个等效元素组。
+
+成功查找基准测试通过按照元素的原始插入顺序查找全部 `n` 个值来完成。
+
+未命中查找基准测试使用不同种子值生成的 `n` 个随机整数进行。
+
+=== GCC 12 + libstdc++-v3, x64
+
+==== 插入
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/gcc/running insertion.xlsx.practice.png[width=250,link=_images/benchmarks-set/gcc/running insertion.xlsx.practice.png,window=_blank]
+|image::benchmarks-set/gcc/running insertion.xlsx.practice non-unique.png[width=250,link=_images/benchmarks-set/gcc/running insertion.xlsx.practice non-unique.png,window=_blank]
+|image::benchmarks-set/gcc/running insertion.xlsx.practice non-unique 5.png[width=250,link=_images/benchmarks-set/gcc/running insertion.xlsx.practice non-unique 5.png,window=_blank]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/gcc/running insertion.xlsx.practice norehash.png[width=250,link=_images/benchmarks-set/gcc/running insertion.xlsx.practice norehash.png,window=_blank]
+|image::benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique.png[width=250,link=_images/benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique.png,window=_blank]
+|image::benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique 5.png[width=250,link=_images/benchmarks-set/gcc/running insertion.xlsx.practice norehash non-unique 5.png,window=_blank]
+
+h|非重复元素, + 预先 `reserve` h|重复元素, + 预先 `reserve` h|重复元素, + 最大负载因子 5, + 预先 `reserve`
+
+|===
+
+==== 擦除
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/gcc/scattered erasure.xlsx.practice.png[width=250,link=_images/benchmarks-set/gcc/scattered erasure.xlsx.practice.png,window=_blank]
+|image::benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique.png[width=250,link=_images/benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique.png,window=_blank]
+|image::benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique 5.png[width=250,link=_images/benchmarks-set/gcc/scattered erasure.xlsx.practice non-unique 5.png,window=_blank]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|
+|image::benchmarks-set/gcc/scattered erasure by key.xlsx.practice non-unique.png[width=250,link=_images/benchmarks-set/gcc/scattered erasure by key.xlsx.practice non-unique.png,window=_blank]
+|image::benchmarks-set/gcc/scattered erasure by key.xlsx.practice non-unique 5.png[width=250,link=_images/benchmarks-set/gcc/scattered erasure by key.xlsx.practice non-unique 5.png,window=_blank]
+
+|
+h|通过键操作, 重复元素 h|通过键操作, 重复元素, + 最大负载因子 5
+
+|===
+
+==== 成功查找
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/gcc/scattered successful looukp.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/gcc/scattered successful looukp.xlsx.practice.png]
+|image::benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique.png]
+|image::benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/gcc/scattered successful looukp.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+==== 未命中查找
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice.png]
+|image::benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique.png]
+|image::benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/gcc/scattered unsuccessful looukp.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+=== Clang 15 + libc++, x64
+
+==== 插入
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/clang_libcpp/running insertion.xlsx.practice.png[width=250, window=_blank,link=_images/benchmarks-set/clang_libcpp/running insertion.xlsx.practice.png]
+|image::benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique.png[width=250, window=_blank,link=_images/benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique.png]
+|image::benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique 5.png[width=250, window=_blank,link=_images/benchmarks-set/clang_libcpp/running insertion.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash.png]
+|image::benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique.png]
+|image::benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/running insertion.xlsx.practice norehash non-unique 5.png]
+
+h|非重复元素, + 预先 `reserve` h|重复元素, + 预先 `reserve` h|重复元素, + 最大负载因子 5, + 预先 `reserve`
+
+|===
+
+==== 擦除
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice.png]
+|image::benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique.png]
+|image::benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered erasure.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|
+|image::benchmarks-set/clang_libcpp/scattered erasure by key.xlsx.practice non-unique.png[width=250,link=_images/benchmarks-set/clang_libcpp/scattered erasure by key.xlsx.practice non-unique.png,window=_blank]
+|image::benchmarks-set/clang_libcpp/scattered erasure by key.xlsx.practice non-unique 5.png[width=250,link=_images/benchmarks-set/clang_libcpp/scattered erasure by key.xlsx.practice non-unique 5.png,window=_blank]
+
+|
+h|通过键操作, 重复元素 h|通过键操作, 重复元素, + 最大负载因子 5
+
+|===
+
+==== 成功查找
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice.png]
+|image::benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique.png]
+|image::benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered successful looukp.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+==== 未命中查找
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice.png]
+|image::benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique.png]
+|image::benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/clang_libcpp/scattered unsuccessful looukp.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+=== Visual Studio 2022 + Dinkumware, x64
+
+==== 插入
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/vs/running insertion.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/vs/running insertion.xlsx.practice.png]
+|image::benchmarks-set/vs/running insertion.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/vs/running insertion.xlsx.practice non-unique.png]
+|image::benchmarks-set/vs/running insertion.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/vs/running insertion.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/vs/running insertion.xlsx.practice norehash.png[width=250,window=_blank,link=_images/benchmarks-set/vs/running insertion.xlsx.practice norehash.png]
+|image::benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique.png]
+|image::benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/vs/running insertion.xlsx.practice norehash non-unique 5.png]
+
+h|非重复元素, + 预先 `reserve` h|重复元素, + 预先 `reserve` h|重复元素, + 最大负载因子 5, + 预先 `reserve`
+
+|===
+
+==== 擦除
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/vs/scattered erasure.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered erasure.xlsx.practice.png]
+|image::benchmarks-set/vs/scattered erasure.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered erasure.xlsx.practice non-unique.png]
+|image::benchmarks-set/vs/scattered erasure.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered erasure.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|
+|image::benchmarks-set/vs/scattered erasure by key.xlsx.practice non-unique.png[width=250,link=_images/benchmarks-set/vs/scattered erasure by key.xlsx.practice non-unique.png,window=_blank]
+|image::benchmarks-set/vs/scattered erasure by key.xlsx.practice non-unique 5.png[width=250,link=_images/benchmarks-set/vs/scattered erasure by key.xlsx.practice non-unique 5.png,window=_blank]
+
+|
+h|通过键操作, 重复元素 h|通过键操作, 重复元素, + 最大负载因子 5
+
+|===
+
+==== 成功查找
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/vs/scattered successful looukp.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered successful looukp.xlsx.practice.png]
+|image::benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique.png]
+|image::benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered successful looukp.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+==== 未命中查找
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice.png]
+|image::benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique.png]
+|image::benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique 5.png[width=250,window=_blank,link=_images/benchmarks-set/vs/scattered unsuccessful looukp.xlsx.practice non-unique 5.png]
+
+h|非重复元素 h|重复元素 h|重复元素, + 最大负载因子 5
+
+|===
+
+== boost::unordered_(flat|node)_map
+
+所有基准测试均为使用以下链接来创建的:
+
+* https://abseil.io/docs/cpp/guides/container[`absl::flat++_++hash++_++map`^]`++<++uint64++_++t, uint64++_++t++>++`
+* `boost::unordered_map`
+* `boost::unordered_flat_map`
+* `boost::unordered_node_map`
+
+源代码可 https://github.com/boostorg/boost_unordered_benchmarks/tree/boost_unordered_flat_map[在此处获取] 。
+
+插入基准测试的操作将插入 `n` 个随机值,其中 `n` 的范围在10,000至1000万之间。
+
+擦除基准测试会遍历全部 `n` 个元素,并删除其中键值为奇数的元素(平均约占50%)。
+
+成功查找基准测试通过按照元素的原始插入顺序查找全部 `n` 个值来完成。
+
+未命中查找基准测试使用不同种子值生成的 `n` 个随机整数进行。
+
+
+=== GCC 12, x64
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/gcc-x64/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x64/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/gcc-x64/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x64/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/gcc-x64/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x64/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/gcc-x64/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x64/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+=== Clang 15, x64
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/clang-x64/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x64/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-x64/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x64/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-x64/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x64/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-x64/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x64/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+=== Visual Studio 2022, x64
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/vs-x64/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x64/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/vs-x64/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x64/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/vs-x64/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x64/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/vs-x64/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x64/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+=== Clang 12, ARM64
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/clang-arm64/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-arm64/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-arm64/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-arm64/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-arm64/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-arm64/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-arm64/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-arm64/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+=== GCC 12, x86
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/gcc-x86/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x86/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/gcc-x86/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x86/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/gcc-x86/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x86/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/gcc-x86/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/gcc-x86/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+=== Clang 15, x86
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/clang-x86/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x86/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-x86/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x86/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-x86/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x86/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/clang-x86/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/clang-x86/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+=== Visual Studio 2022, x86
+
+
+[caption=]
+[cols="4*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-flat_map/vs-x86/Running insertion.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x86/Running insertion.xlsx.plot.png]
+|image::benchmarks-flat_map/vs-x86/Running erasure.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x86/Running erasure.xlsx.plot.png]
+|image::benchmarks-flat_map/vs-x86/Scattered successful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x86/Scattered successful looukp.xlsx.plot.png]
+|image::benchmarks-flat_map/vs-x86/Scattered unsuccessful looukp.xlsx.plot.png[width=250,window=_blank,link=_images/benchmarks-flat_map/vs-x86/Scattered unsuccessful looukp.xlsx.plot.png]
+
+h|插入的执行 h|擦除的执行 h|成功查找 h|未命中查找
+
+|===
+
+== boost::concurrent_(flat|node)_map
+
+所有基准测试均为使用以下链接来创建的:
+
+* `https://spec.oneapi.io/versions/latest/elements/oneTBB/source/containers/concurrent_hash_map_cls.html[oneapi::tbb::concurrent_hash_map^]`
+* `https://github.com/greg7mdp/gtl/blob/main/docs/phmap.md[gtl::parallel_flat_hash_map^]` (含64个子映射)
+* `boost::concurrent_flat_map`
+* `boost::concurrent_node_map`
+
+源代码可 https://github.com/boostorg/boost_unordered_benchmarks/tree/boost_concurrent_flat_map[在此处获取] 。
+
+基准测试使用__T__个线程(数量1至16之间)并发执行随机选择的操作,这些操作包括**更新**、**成功查找**和**未命中查找**三种类型。操作使用的键遵循 https://en.wikipedia.org/wiki/Zipf%27s_law#Formal_definition[齐夫分布] ,并采用不同的__偏斜__参数:偏斜值越高,键的分布越集中在取值区间的较低数值区域。
+
+`boost::concurrent_flat_map` 和 `boost::concurrent_node_map` 分别通过常规访问和 xref:concurrent.adoc#concurrent_bulk_visitation[批量访问] 进行演练:在批量访问的情况下,查找键会缓存在本地数组中,每当缓冲区大小达到 `xref:reference/concurrent_flat_map.adoc#concurrent_flat_map_constants[bulk_visit_size]` 时,再一次性处理这些键。
+
+=== GCC 12, x64
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x64/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
+
+=== Clang 15, x64
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x64/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
+
+=== Visual Studio 2022, x64
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x64/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
+
+=== Clang 12, ARM64
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-arm64/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
+
+=== GCC 12, x86
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/gcc-x86/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
+
+=== Clang 15, x86
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/clang-x86/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
+
+=== Visual Studio 2022, x86
+
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.500k, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.500k, 0.01.png"]
+|image::benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.500k, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.500k, 0.5.png"]
+|image::benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.500k, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.500k, 0.99.png"]
+
+h|50万次更新, 450万次查找 + 偏斜=0.01 h|50万次更新, 450万次查找 + 偏斜=0.5 h|50万次更新, 450万次查找 + 偏斜=0.99 |===
+
+[caption=]
+[cols="3*^.^a", frame=all, grid=all]
+|===
+
+|image::benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.5M, 0.01.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.5M, 0.01.png"]
+|image::benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.5M, 0.5.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.5M, 0.5.png"]
+|image::benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.5M, 0.99.png[width=250,window=_blank,link="_images/benchmarks-concurrent_map/vs-x86/Parallel workload.xlsx.5M, 0.99.png"]
+
+h|500万次更新, 4500万次查找 + 偏斜=0.01 h|500万次更新, 4500万次查找 + 偏斜=0.5 h|500万次更新, 4500万次查找 + 偏斜=0.99 |===
diff --git a/doc/modules/ROOT/pages/bibliography_zh_Hans.adoc b/doc/modules/ROOT/pages/bibliography_zh_Hans.adoc
new file mode 100644
index 0000000..4c4b0b4
--- /dev/null
+++ b/doc/modules/ROOT/pages/bibliography_zh_Hans.adoc
@@ -0,0 +1,12 @@
+[#bibliography]
+
+:idprefix: bibliography_
+
+= 文献目录
+
+* _C/C++ Users Journal_. February, 2006. Pete Becker. http://www.ddj.com/cpp/184402066[STL and TR1: :第三部分 — 无序容器^] 。 +
+关于标准无序容器的介绍性文章。
+* __维基百科__中的 https://en.wikipedia.org/wiki/Hash_table[哈希表^] 。 +
+这是关于哈希表实现原理的概述,重点探讨了链地址法和开放地址法两种实现路径的差异。
+* Peter Dimov,2022年。 https://pdimov.github.io/articles/unordered_dev_plan.html[Boost.Unordered库开发计划^] 。
+
diff --git a/doc/modules/ROOT/pages/buckets_zh_Hans.adoc b/doc/modules/ROOT/pages/buckets_zh_Hans.adoc
new file mode 100644
index 0000000..ceef73e
--- /dev/null
+++ b/doc/modules/ROOT/pages/buckets_zh_Hans.adoc
@@ -0,0 +1,101 @@
+[#buckets]
+:idprefix: buckets_
+
+= 哈希表基础
+
+该容器由若干__桶__组成,每个桶可容纳任意数量的元素。例如,下图展示了一个包含7个桶的 xref:reference/unordered_set.adoc#unordered_set[boost::unordered_set],其中存储着5个元素( `A` 、 `B` 、 `C` 、 `D` 和 `E` )(此示意图仅为演示用途,实际容器通常包含更多桶)。
+
+image::buckets.png[]
+
+容器通过哈希函数 `Hash` 作用于元素的键来确定其所属的桶(对于集合而言,键即元素本身,但为统一集合与映射表的术语仍称作键)。该函数返回 `std::size_t` 类型的值。由于 `std::size_t` 的取值范围远大于桶的数量,容器会对此值进行二次转换以确定元素应存入的桶。
+
+根据指定键检索元素的过程非常简单:首先对键执行相同处理以定位对应桶,随后通过相等性谓词 `Pred` 将键与桶内元素进行比较以寻找匹配项。若哈希函数表现良好,元素将均匀分布于各桶中,此时仅需检查少量元素即可完成检索。
+
+关于哈希函数与相等性谓词的详细说明请参阅 xref:hash_equality.adoc#hash_equality[后续章节] 。
+
+如图所示, `A` 与 `D` 被置于同一桶内。在此桶内查找元素时最多需要进行 2 次比对,这会降低检索效率,该现象称为**冲突**。为维持高效运作,我们需尽可能减少冲突的发生。
+
+若使用 xref:reference/unordered_flat_set.adoc[boost::unordered_flat_set]替代 `boost::unordered_set` ,其结构示意图将呈现如下形式:
+
+image::buckets-oa.png[]
+
+在开放寻址式容器中,每个桶最多只能容纳一个元素;若发生冲突(如示例中的元素 `D` 的情况),该元素将使用原始位置附近的其他可用桶。基于此简化设计,Boost.Unordered开放寻址容器仅提供极其有限的桶访问API。
+
+[caption=, title='Table {counter:table-counter}. Methods for Accessing Buckets']
+[cols="1,.^1", frame=all, grid=rows]
+|===
+2+^h| *所有容器* h|*方法* h|*描述*
+
+|`size_type bucket_count() const`
+|The number of buckets.
+
+2+^h| *仅限闭寻址容器* h|*方法* h|*描述*
+
+|`size_type max_bucket_count() const`
+|An upper bound on the number of buckets.
+|`size_type bucket_size(size_type n) const`
+|The number of elements in bucket `n`.
+
+|`size_type bucket(key_type const& k) const`
+|Returns the index of the bucket which would contain `k`.
+
+|`local_iterator begin(size_type n)`
+1.6+|返回编号为 `n` 的桶的起始与末尾迭代器。
+
+|`local_iterator end(size_type n)`
+
+|`const_local_iterator begin(size_type n) const`
+
+|`const_local_iterator end(size_type n) const`
+
+|`const_local_iterator cbegin(size_type n) const`
+
+|`const_local_iterator cend(size_type n) const`
+
+|===
+
+== 桶数量控制
+
+当无序关联容器中的元素不断增加时,冲突次数会随之上升,从而导致性能下降。为解决此问题,容器会在插入元素过程中自动增加桶的数量。用户也可以通过调用 `rehash` 方法来按需调整容器的桶数量。
+
+标准规范虽未强制规定桶数量的具体选择方式,但基于容器的__负载因子__(即元素数量与桶数量的比值)提出了若干要求。同时,容器还设有一个__最大负载因子__,其运行过程中需始终将实际负载因子维持在该阈值以下。
+
+用户无法直接控制桶的数量,但可通过以下两种方式间接调控:
+
+* 用户可在构造容器或调用 `rehash` 方法时指定桶数量的最小值。
+* 用户可通过调用 `max_load_factor` 方法来设定最大负载因子的建议值。
+
+`max_load_factor` 并不允许用户自行设定最大负载因子,该方法仅用于提供__提示__。即便如此,标准也并未强制要求容器必须严格遵守该数值。唯一强制要求负载因子必须小于最大值的场景是在调用 `rehash` 方法之后。但大多数实现会尝试将元素数量维持在最大负载因子以下,并将最大负载因子设定为与提示值相同或接近——除非用户提供的提示值过小或过大。
+
+[caption=, title='Table {counter:table-counter}. Methods for Controlling Bucket Size']
+[cols="1,.^1", frame=all, grid=rows]
+|===
+2+^h| *所有容器* h|*方法* h|*描述*
+
+|`X(size_type n)`
+|Construct an empty container with at least `n` buckets (`X` is the container type).
+
+|`X(InputIterator i, InputIterator j, size_type n)`
+|Construct an empty container with at least `n` buckets and insert elements from the range `[i, j)` (`X` is the container type).
+
+|`float load_factor() const`
+|The average number of elements per bucket.
+
+|`float max_load_factor() const`
+|Returns the current maximum load factor.
+
+|`float max_load_factor(float z)`
+|Changes the container's maximum load factor, using `z` as a hint. +
+**开放寻址与并发容器:**此函数无效,用户不允许更改最大负载因子。
+
+|`void rehash(size_type n)`
+|Changes the number of buckets so that there at least `n` buckets, and so that the load factor is less than the maximum load factor.
+
+2+^h| *仅限开放寻址与并发容器* h|*方法* h|*描述*
+
+|`size_type max_load() const`
+|Returns the maximum number of allowed elements in the container before rehash.
+
+|===
+
+关于开放寻址与并发容器的 `max_load` 注意事项:在容器创建或执行 `rehash` 后,最大负载值将保持为 `max_load_factor() * bucket_count()` ;但在高负载场景下执行元素删除操作时,该值可能轻微下降。例如,若某个 xref:reference/unordered_flat_map.adoc#unordered_flat_map[boost::unordered_flat_map] 的 `size()` 已接近 `max_load()` 阈值,随后删除 1,000 个元素时, `max_load()` 可能减少约数十个元素。此机制是Boost.Unordered为保持性能稳定而采取的内部机制,用户在规划无重组插入操作时需予以考虑。
diff --git a/doc/modules/ROOT/pages/changes_zh_Hans.adoc b/doc/modules/ROOT/pages/changes_zh_Hans.adoc
new file mode 100644
index 0000000..c5b4702
--- /dev/null
+++ b/doc/modules/ROOT/pages/changes_zh_Hans.adoc
@@ -0,0 +1,392 @@
+[#changes]
+= 变更日志
+
+:idprefix: changes_ :svn-ticket-url: https://svn.boost.org/trac/boost/ticket :github-pr-url: https://github.com/boostorg/unordered/pull :cpp: C++
+
+== 版本 1.89.0
+
+* 已弃用的 boost::unordered::hash_is_avalanching 现在是
+在 中对 boost::hash_is_avalanching 的使用声明。请直接使用该头文件代替。 将在未来被移除。
+* 为开放寻址容器新增 `pull(const_iterator)` 操作,该操作
+支持通过移动构造机制高效移除并检索指定元素。
+
+== 版本 1.88.0
+
+* 使用 Antora 将文档重构为多页面格式。
+
+== 版本 1.87.0 - 重大更新
+
+* 新增基于节点的并发容器 `boost::concurrent_node_map` 与 `boost::concurrent_node_set` 。
+* 为并发容器新增 `insert_and_visit(x, f1, f2)` 及类似操作,这些操作
+支持在插入元素后立即对其进行访问(而 `insert_or_visit(x, f)` 仅在未执行插入时才访问元素)。
+* 在特定 `boost::concurrent_flat_set` 操作中启用独占锁访问机制,
+以支持对元素进行安全的可变修改(https://github.com/boostorg/unordered/pull/265[PR#265])。
+* 在 Visual Studio Natvis 中,现支持使用带花式指针分配器的任意容器。只要为花式指针类型编写了相应的 Natvis 自定义“Intrinsic”函数,即可适用于所有花式指针类型。
+* 为所有容器和迭代器添加 GDB 美化打印器。对于使用花式指针分配器的容器,需先为花式指针类型编写对应的美化打印器方可正常使用。
+* 修复开放寻址容器中 `std::initializer_list` 的 赋值问题
+(https://github.com/boostorg/unordered/pull/277[PR#277])。
+* 通过内部将可调用对象的 `std::reference_wrapper` 传递给迭代器对重载,现允许向并发容器的 `insert_{and|or}_[c]visit` 的 `std::initializer_list` 重载传递不可复制的可调用对象。
+
+
+== 版本 1.86.0
+
+* 当头文件 `` 可用时,新增容器 `pmr` 别名。 `boost::unordered::pmr::[container]` 别名指向使用 `std::pmr::polymorphic_allocator` 分配器类型的 `boost::unordered::[container]` 。
+* 为开放寻址容器与并发容器增设内部统计功能,可计算并提供受哈希函数质量影响的统计指标。通过全局宏 `BOOST_UNORDERED_ENABLE_STATS` 启用。
+* 雪崩哈希函数现在必须通过内嵌 `value` 常量设为 `true` 的 `is_avalanching` typedef 来标记(通常将 `is_avalanching` 定义为 `std::true_type`)。 `using is_avalanching = void` 已被弃用,但为了向后兼容性仍予保留。
+* 为容器和迭代器添加 Visual Studio Natvis 框架的自定义可视化功能。此功能适用于所有使用原始指针分配器的容器。在此版本中,若容器或迭代器的分配器使用花式指针,则暂不支持该功能,此问题可能在后续版本中解决。
+
+== 版本 1.85.0
+
+* 优化 `emplace()` 对 `value_type` 或 `init_type` (如适用)参数的实现,使其无需创建中间对象即可直接处理参数,因为该参数类型与待构造的中间对象类型完全相同。
+* 优化 map 容器的 `emplace()` 对 `k,v` 参数的处理:将对象构造延迟到确认需要插入元素时执行。此优化在映射的 `key_type` 可移动构造或 `k` 参数为 `key_type` 类型时生效。
+* 修复对含 `explicit` 复制构造函数的分配器的支持(https://github.com/boostorg/unordered/pull/234[PR#234])。
+* 修复 `unordered_multimap::find(k, hash, eq)` 的 `const` 版本中的缺陷(https://github.com/boostorg/unordered/pull/238[PR#238])。
+
+== 版本 1.84.0 - 重大更新
+
+* 新增 `boost::concurrent_flat_set` 。
+* 为并发容器新增 `[c]visit_while` 操作,
+提供串行与并行两种执行模式。
+* 实现高效双向移动构造(从
+`boost::unordered_flat_(map|set)` 到 `boost::concurrent_flat_(map|set)` 及反向的)
+* 为并发容器新增批量访问功能以提升查找性能。
+* 新增调试模式机制,用于检测用户代码对
+并发容器的非法重入操作。
+* 为所有容器及其(非本地)迭代器类型添加 Boost.Serialization 支持。
+* 为开放寻址容器与并发容器新增对花式指针的支持,此特性支持诸如使用 Boost.Interprocess 分配器在共享内存中构建容器等应用场景。
+这使得像使用 Boost.Interprocess 分配器在共享内存中构造容器这样的场景成为可能。
+* 修复闭寻址容器局部迭代器的成员指针运算符缺陷
+(https://github.com/boostorg/unordered/pull/221[PR#221] ,致谢 GitHub 用户 vslashg 发现并修复)。
+* 从此版本起, `boost::unordered_[multi]set` 和 `boost::unordered_[multi]map`
+仅支持 C{plus}{plus}11 及以上版本。
+
+== 版本 1.83.0 - 重大更新
+
+* 新增基于开放寻址的快速线程安全哈希映射容器 `boost::concurrent_flat_map` 。
+* 提升开放寻址容器的迭代性能。
+* 在开放寻址容器中,原无返回值的 `erase(iterator)` 方法,现在
+返回一个可转换为下一元素迭代器的代理对象。此改进支持典型的 `it = c.erase(it)` 编程范式,且当未使用返回的代理对象时不会产生任何性能开销。
+
+== 版本 1.82.0 - 重大更新
+
+* 计划弃用 C{plus}{plus}03 支持。Boost 1.84.0 将不再支持
+C{plus}{plus}03 模式,C{plus}{plus}11 将成为使用该库的最低要求。
+* 新增基于节点的开放寻址容器
+`boost::unordered_node_map` 与 `boost::unordered_node_set`。
+* 将异构查找功能扩展至更多成员函数
+(根据https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2363r5.html[P2363] 规范) 。
+* 取代开放寻址容器原有的后混合处理流程(采用
+基于常量扩展乘法的新算法)。
+* 修复内部 emplace() 实现中存在的缺陷:
+该缺陷曾导致栈局部类型未能使用容器的分配器进行正确构造,从而违反分配器感知构造规范。
+
+== 版本 1.81.0 - 重大更新
+
+* 新增基于开放寻址的快速容器`boost::unordered_flat_map` and `boost::unordered_flat_set`。
+(基于开放寻址的)
+* 为所有容器添加 CTAD 推导指引。
+* 补充 https://cplusplus.github.io/LWG/issue2713[LWG 问题 2713] 中要求的缺失构造函数。
+
+== 版本 1.80.0 - 重大更新
+
+* 重构内部实现以显著提升性能
+* 允许 使用 `final` 修饰的 Hasher 和 KeyEqual 对象
+* 更新文档,新增性能基准对比图及关于新内部数据结构的说明
+(数据结构)
+
+== 版本 1.79.0
+
+* 增强 C{plus}{plus}20 标准兼容性:
+** 所有容器均已完成升级,支持异构查找操作 `count` 、 `equal_range` 及 `find` 。 ** 所有容器现均已实现成员函数 `contains` 。 ** 所有容器均已实现 `erase_if` 功能。
+* 增强 C{plus}{plus}23 标准兼容性:
+** 所有容器均已完成升级,支持异构版本的 `erase` 与 `extract` 操作。
+* 更改 `reserve` 的行为,
+使其立即分配桶数组空间(https://github.com/boostorg/unordered/pull/59[PR#59])。
+* 测试套件中的多项警告修复。
+* 将内部代码更新为使用 `boost::allocator_traits` 。
+* 切换至斐波那契哈希算法。
+* 将文档编写格式从 QuickBook 切换为 AsciiDoc。
+
+== 版本 1.67.0
+
+* 增强 C{plus}{plus}17 标准兼容性:
+** 新增标准的模板推导指南。 ** 在节点句柄中采用简化的 `optional` 实现,以使其 更符合标准规范。 ** 为 `swap` 、 `operator=` 及节点句柄补充缺失的 `noexcept` 规范,调整实现以符合规范要求。在实现中使用 `std::allocator_traits::is_always_equal` (若该特性不可用则采用自有实现),以及 `boost::is_nothrow_swappable` 在实现中。
+* 增强 C{plus}{plus}20 标准兼容性:
+** 使用具有 C{plus}{plus}20 提案语义的 `boost::to_address` , 来替代原有的自定义实现。
+* 向迭代器添加 `element_type` 类型定义,以支持 `std::pointer_traits` 的
+正常工作。
+* 在新版 Visual C{plus}{plus} 及
+其他使用 Dinkumware 标准库的环境中使用 `std::piecewise_construct` ,现在使用 Boost.Predef 来检查编译器和标准库版本。
+* 使用 `std::iterator++_++traits` 替代 boost 迭代器特征库,
+以消除对 Boost.Iterator 的依赖。
+* 移除迭代器对 `std::iterator` 的继承
+(该基类在 C{plus}{plus}17 中已弃用),感谢 Daniela Engert的贡献(https://github.com/boostorg/unordered/pull/7[PR#7])。
+* 停止使用 `BOOST_DEDUCED_TYPENAME` 。
+* 更新部分 Boost 头文件包含路径。
+* 重命名部分内部方法和变量。
+* 多项测试改进。
+* 多项内部变更。
+
+== 版本 1.66.0
+
+* 更简化的移动构造实现。
+* 文档修正(https://github.com/boostorg/unordered/pull/6[GitHub #6])。
+
+== 版本 1.65.0
+
+* 向 `quick_erase` 和 `erase_return_void` 添加弃用属性。
+本次确认将在未来版本中移除这两个接口。
+* 局部标准符合性修正:
+** `swap` 自由函数的 `noexcept` 规范。** 补充缺失的 `insert(P&&)` 方法。
+
+== 版本 1.64.0
+
+* 初步支持 C{plus}{plus}17 新成员函数:
+`unordered_map` 中的 `insert_or_assign` 和 `try_emplace`,
+* 初步支持 `merge` 与 `extract` 操作。
+目前尚未支持在 `unordered_map` 与 `unordered_multimap` 之间,或 `unordered_set` 与 `unordered_multiset` 之间转移节点。该功能有望在下一版 Boost 中提供。
+
+== 版本 1.63.0
+
+* 检查 `insert` / `emplace_hint` 操作中提示迭代器的有效性。
+* 修复部分警告(主要出现在测试中)。
+* 为参数数量较少的情况手动编写 `emplace_args` 代码,
+以减轻模板错误消息的负担。
+* 移除 emplace 参数中多余的 `boost::forward` 调用,
+以修复旧版 Visual C{plus}{plus} 中字面量字符串的就地构造问题。
+* 修复赋值操作中的异常安全问题。若桶分配过程
+抛出异常,可能导致哈希函数与相等性判断函数被覆盖,而现有元素仍保留在容器中。这将造成函数对象与容器元素不匹配,进而引发元素错置桶位及等价元素处理错误的问题。
+* 多项参考文档改进。
+* 增强的分配器支持(https://svn.boost.org/trac/boost/ticket/12459[#12459])。
+* 将无参构造函数改为隐式声明。
+* 实现缺失的分配器感知构造函数。
+* 修复空容器在设置哈希函数与键值相等性判断函数时存在的问题。
+* 从文档示例中移除 unary/binary_function。
+这两者在 C{plus}{plus}17 中已被移除。
+* emplace 方法现支持 10 个构造参数。其设计本应支持最多 10 个参数,
+但由于预处理代码中存在差一错误,仅支持 9 个参数。
+
+== 版本 1.62.0
+
+* 停止使用已弃用的 `boost::iterator` 组件 。
+* 移除 `BOOST_NO_STD_DISTANCE` 的兼容性代码。
+* 移除 `BOOST_UNORDERED_DEPRECATED_EQUALITY` 警告。
+* 采用更简化的赋值操作实现,修复了
+`unordered_multiset` 与 `unordered_multimap` 的异常安全问题,但性能可能略有下降。
+* 停止使用返回值SFINAE技术,以避免部分旧版本编译器的
+兼容性问题。
+
+== 版本 1.58.0
+
+* 移除常量迭代器中不必要的模板参数。
+* 重命名部分迭代器类中私有的 `iterator` 类型别名,以
+避免某些特征类产生混淆。
+* 修复当使用具有状态且设置了propagate_on_container_move_assign 的分配器时,
+移动赋值操作存在的缺陷(https://svn.boost.org/trac/boost/ticket/10777[#10777])。
+* 修复移动赋值操作中一处罕见的异常安全问题。
+* 修复计算待分配桶数量时可能出现的溢出问题
+(https://github.com/boostorg/unordered/pull/4[GitHub #4])。
+
+== 版本 1.57.0
+
+* 修复迭代器中 `pointer` 类型定义的问题(https://svn.boost.org/trac/boost/ticket/10672[#10672])。
+* 修复 Coverity 警告
+(https://github.com/boostorg/unordered/pull/2[GitHub #2])。
+
+== 版本 1.56.0
+
+* 修复部分变量遮蔽警告(https://svn.boost.org/trac/boost/ticket/9377[#9377])。
+* 修正文档中的分配器用法(https://svn.boost.org/trac/boost/ticket/9719[#9719])。
+* 对整数键始终采用质数桶数量。此修复解决了
+插入连续整数时的性能回归问题,但可能会降低其他使用场景的速度(https://svn.boost.org/trac/boost/ticket/9282[#9282])。
+* 严格遵循 C{plus}{plus}11 标准规定,仅使用分配器构造元素。
+
+== 版本 1.55.0
+
+* 避免部分警告(https://svn.boost.org/trac/boost/ticket/8851[#8851] 、 https://svn.boost.org/trac/boost/ticket/8874[#8874])。
+* 避免通过迭代器上的 ADL 暴露部分细节函数。
+* 遵循标准规范,仅使用分配器的 construct 和 destroy
+方法来构造和析构存储的元素,不将其用于指针等内部数据的操作。
+
+== 版本 1.54.0
+
+* 为标准中指定的方法标注 `noexcept` 。更多方法将在下一
+版本中更新。
+* 若已知哈希函数与相等性谓词均具备无抛出
+移动赋值或移动构造特性,则使用它们。
+
+== 版本 1.53.0
+
+* 移除对旧式变参 pair 构造函数和
+相等性实现的支持,这两项功能自 Boost 1.48 起已被弃用。
+* 停止使用已弃用的配置宏。
+* 更多内部实现变更,包括采用更简化的
+`erase` 方法 实现。
+
+== 版本 1.52.0
+
+* 加速赋值操作:尽可能复用现有节点进行赋值,
+而非创建全新节点并执行复制构造。
+* 修复 `erase_range` 方法中的缺陷(https://svn.boost.org/trac/boost/ticket/7471[#7471])。
+* 回退部分关于节点创建机制的内部变更(尤其
+针对 C{plus}{plus}11 编译器),使 'construct' 和 'destroy' 对 C{plus}{plus}11 分配器更有效。
+* 简化实现,以提高健壮性。
+
+== 版本 1.51.0
+
+* 修复当使用 C{plus}{plus}11 编译器搭配 C{plus}{plus}03 分配器时
+出现的构造/析构问题(https://svn.boost.org/trac/boost/ticket/7100[#7100])。
+* 移除一段 `try..catch` 代码块以支持无异常编译模式。
+* 调整 SFINAE 的实现方式以兼容 g{plus}{plus} 3.4(https://svn.boost.org/trac/boost/ticket/7175[#7175])。
+* 更新为使用新的配置宏。
+
+== 版本 1.50.0
+
+* 修复 `unordered_multiset` 与 `unordered_multimap` 的相等性判断逻辑。
+* https://svn.boost.org/trac/boost/ticket/6857[问题单 6857] :
+实现 `reserve` 。
+* https://svn.boost.org/trac/boost/ticket/6771[问题 6771] :
+规避 gcc 的 `-Wfloat-equal` 编译警告。
+* https://svn.boost.org/trac/boost/ticket/6784[问题单 6784] :
+修复部分 Sun 编译器专用代码。
+* https://svn.boost.org/trac/boost/ticket/6190[问题单 6190] :
+规避 gcc 的 `-Wshadow` 编译警告。
+* https://svn.boost.org/trac/boost/ticket/6905[问题单 6905] :
+使宏中的命名空间与 `bcp` 自定义命名空间兼容(由 Luke Elliott 修复)。
+* 移除部分较小的质数桶数量,因为这些数值
+可能显著增加冲突概率(例如,由于我们使用十进制,5的倍数出现频率很高)。
+* 对于旧版本 Visual C{plus}{plus},优先使用容器库自带的
+`allocator_traits` 实现,因其兼容性更佳。
+* 64 位 std::size_t 机器上使用 2 的幂次桶数量,通过 Thomas
+Wang 哈希函数选择桶(因取模运算在 64 位值上极慢)。
+* 部分内部变更。
+
+== 版本 1.49.0
+
+* 修复因意外出现的异常赋值操作而产生的编译警告。
+* 轻微优化错误消息。
+
+== 版本 1.48.0 - 重大更新
+
+本本次为重大更新:容器已改用 Boost.Move 的移动操作模拟实现,并显著提升了对 C{plus}{plus}11 标准的符合性。详见 xref:compliance.adoc[标准合规性章节] 。
+
+该容器现满足 C{plus}{plus}11 的复杂度要求,但为此会占用稍多内存。这意味着 `quick_erase` 与 `erase_return_void` 接口已不再必需,将在未来版本中移除。
+
+C{plus}{plus}11 支持导致部分破坏性变更:
+
+* 相等性比较已改为遵循 C{plus}{plus}11 规范。
+在包含等价键的容器中,原先要求同一组等价键内的元素必须顺序一致才被视为相等,现在则允许它们互为排列。如需使用旧行为,请定义宏 `BOOST_UNORDERED_DEPRECATED_EQUALITY` 。
+
+* 当两个待交换容器的分配器不相等时,swap 操作的行为发生变更。
+旧版本会通过相应的分配器分配新节点,现在则改为:若分配器包含 `propagate_on_container_swap` 成员结构体且其 `propagate_on_container_swap::value` 为 true,则会交换分配器本身。
+
+* 现在当调用分配器的 `construct` 与 `destroy` 时,直接传入原始指针,
+而非分配器定义的 `pointer` 类型。
+
+* `emplace` 方法原先模拟了
+早期 C{plus}{plus}0x 草案中的变参 pair 构造函数。由于该特性已被移除,现不再提供此模拟实现。当前仅模拟新的 `piecewise_construct` pair 构造函数,但需使用 `boost::piecewise_construct` 作为参数。若需启用旧版变参构造函数的模拟行为,请定义宏 `BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT` 。
+
+== 版本 1.45.0
+
+* 修复了在使用返回 `value_type` 副本的迭代器插入 `unordered_map` 或 `unordered_set` 时的一个错误。
+(使用返回 `value_type` 副本)
+
+== 版本 1.43.0
+
+* https://svn.boost.org/trac/boost/ticket/3966[问题单 3966] :
+`erase_return_void` 更名为 `quick_erase` (符合 http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#579[当前迭代器擦除缓慢的解决方案^])。旧方法名出于向后兼容性予以保留,但已被视为弃用接口,将在未来版本中移除。
+* 使用 Boost.Exception。
+* 停止使用已弃用的 `BOOST_HAS_*` 系列宏。
+
+== 版本 1.42.0
+
+* 支持使用不完整值类型来实例化容器。
+* 减少编译警告数量(主要出现在测试中)。
+* 提升 Codegear 兼容性。
+* https://svn.boost.org/trac/boost/ticket/3693[问题单 3693] :
+新增 `erase_return_void` 作为临时解决方案,以应对当前 `erase` 方法因需查找下一元素返回迭代器而可能产生的效率问题。
+* 新增针对兼容键的模板化 find 重载。
+* https://svn.boost.org/trac/boost/ticket/3773[问题单 3773] :
+为 `ptrdiff_t` 添加缺失的 `std` 限定符。
+* 调整代码格式,使大多数代码行不超过 80 字符。
+
+== 版本 1.41.0 - 重大更新
+
+* 初始版本曾大量使用
+宏来规避旧式编译器薄弱的模板支持能力。鉴于现已不再支持这些编译器,且宏的使用逐渐成为维护负担,现将实现类重构为使用模板替代宏。
+
+* 通过 `boost::compressed_pair` 实现 EBO 及微调函数缓冲区
+(现使用 bool 替代成员指针),容器对象的内存占用得以减小。
+
+* 桶采用延迟分配机制,这意味着构造空容器时
+不会分配任何内存。
+
+== 版本 1.40.0
+
+* https://svn.boost.org/trac/boost/ticket/2975[问题单 2975] :
+将质数列表存储为预处理序列,确保未来再次调整列表长度时能自动保持正确。
+* https://svn.boost.org/trac/boost/ticket/1978[问题单 1978] :
+为所有编译器实现 `emplace` 。
+* https://svn.boost.org/trac/boost/ticket/2908[问题单 2908] 、
+https://svn.boost.org/trac/boost/ticket/3096[问题单 3096] :针对旧版 borland 的变通方案(包括为所有容器添加显式析构函数)。
+* https://svn.boost.org/trac/boost/ticket/3082[问题单 3082] :
+禁用 Visual C{plus}{plus} 编译器的错误警告。
+* 对 C{plus}{plus}0x 特性提供优化方案,以应对头文件不可用的情况。
+* 默认创建更少的桶。
+
+== 版本 1.39.0
+
+* https://svn.boost.org/trac/boost/ticket/2756[问题单 2756] :规避
+Visual C{plus}{plus} 2009 的编译警告。
+* 对实现、测试及文档进行其他少量内部调整。
+(文档)
+* 避免 `operator[]` 中不必要的复制。
+* https://svn.boost.org/trac/boost/ticket/2975[问题单 2975] :修正
+质数列表长度。
+
+== 版本 1.38.0
+
+* 使用 link:../../../../core/swap.html[`boost::swap`] 。
+* https://svn.boost.org/trac/boost/ticket/2237[问题单 2237] :
+补充说明:如果两个对象的相等谓词不等价,则它们的相等与不等运算符的行为未定义。感谢 Daniel Krügler。
+* https://svn.boost.org/trac/boost/ticket/1710[问题单 1710]:
+采用更长的质数列表。感谢 Thorsten Ottosen 与 Hervé Brönnimann 的贡献。
+* 使用
+link:../../../../type_traits/index.html[对齐存储] 来存储类型。这改变了利用分配器构造节点的方式:原先通过两次调用分配器的 `construct` 方法分别构造指针和值,现在仅通过单次调用构造节点,随后采用就地构造方式构建值对象。
+* 在可用时支持 C{plus}{plus}0x 初始化列表(当前
+仅 g{plus}{plus} 4.4 的 C{plus}{plus}0x 模式)。
+
+== 版本 1.37.0
+
+* 将带提示的 `emplace` 重载更名为 `emplace++_++hint` 。
+(根据 http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2691.pdf[n2691^] 规范)
+* 在 `` 与
+`` 路径下提供前向声明头文件。
+* 将所有实现移至 `boost/unordered` 内,以支持
+模块化并便于跟踪发布版本。
+
+== 版本 1.36.0
+
+首次正式发布。
+
+* 调整内部结构。
+* 移动语义:在支持右值引用的环境中提供完整支持,否则
+使用精简版 Adobe 移动库进行模拟实现。
+* 支持右值引用和变参模板时提供就地构造支持。
+* 节点分配效率更高(当右值引用和变参模板
+可用时)。
+* 新增相等性判断运算符。
+
+== Boost 1.35.0 附加版本 - 2008年3月31日
+
+非官方版本已上传至资源库,适用于 Boost 1.35.0。该版本已采纳评审阶段的多项改进建议。
+
+* 通过 Boost 回归测试,代码可移植性得到显著提升。
+* 修正文档中的多处笔误,并优化文本表述以提升可读性。
+* 修复根据最大负载因子计算容器大小时,浮点数到 `std::size_t` 的转换问题,
+并在计算过程中使用 `double` 类型来提高精度。
+* 修正示例中的部分错误。
+
+== 评审版本
+
+初始评审版本(评审时间:2007年12月7日至12月16日)。
diff --git a/doc/modules/ROOT/pages/compliance_zh_Hans.adoc b/doc/modules/ROOT/pages/compliance_zh_Hans.adoc
new file mode 100644
index 0000000..5d1331b
--- /dev/null
+++ b/doc/modules/ROOT/pages/compliance_zh_Hans.adoc
@@ -0,0 +1,94 @@
+[#compliance]
+= 标准符合性
+
+:idprefix: compliance_
+
+:cpp: C++
+
+== 闭寻址容器
+
+`boost::unordered_[multi]set` 和 `boost::unordered_[multi]map` 为支持 {cpp}11 或更高版本的编译器提供了符合最新标准修订版中 {cpp} 无序关联容器规范的实现,仅有极少量的已知偏差。这些容器完全遵循 https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[分配器感知^] ,并支持 https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[花式指针^]。
+
+=== 推导指引
+
+https://en.cppreference.com/w/cpp/language/class_template_argument_deduction[类模板参数推导 (CTAD)] 的推导指南仅在 C{plus}{plus}17(或更高版本)编译器中可用。
+
+=== 分段式 Pair 就地构造
+
+根据标准规范, `boost::unordered_[multi]map::emplace` 支持 pair 的分段构造:
+
+[source,c++]
+----
+boost::unordered_multimap x;
+
+x.emplace(
+ std::piecewise_construct,
+ std::make_tuple("key"), std::make_tuple(1, 2));
+----
+
+此外,通过非标准接口 `boost::unordered::piecewise_construct` 与 Boost.Tuple 提供相同功能:
+
+[source,c++]
+----
+x.emplace(
+ boost::unordered::piecewise_construct,
+ boost::make_tuple("key"), boost::make_tuple(1, 2));
+----
+
+此特性为保持与 Boost.Unordered 旧版本的向后兼容性而保留:建议用户更新代码以使用 `std::piecewise_construct` 与 `std::tuple` 。
+
+=== 交换
+
+执行交换操作时,当前未通过调用 `swap` 函数来交换 `Pred` 和 `Hash` 对象,而是使用其复制构造函数。因此,在交换过程中可能会因其复制构造函数而抛出异常。
+
+== 开放寻址容器
+
+C++ 标准目前并未提供任何可供遵循的开放定址容器规范,因此 `boost::unordered_flat_set` / `unordered_node_set` 与 `boost::unordered_flat_map` / `unordered_node_map` 分别借鉴 `std::unordered_set` 和 `std::unordered_map` 的设计,并在其内部数据结构(与标准规定的闭寻址方式截然不同)允许或需要时,对接口进行相应调整。
+
+Boost.Unordered 提供的开放寻址容器仅兼容符合 C{plus}{plus}1(或更高版本)的编译器,且不再对移动语义、变参模板等语言特性进行模拟实现。这些容器完全符合 https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[分配器感知] 规范,并支持 https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[花式指针] 。
+
+
+与 C{plus}{plus} 无序关联容器的主要区别在于:
+
+* 总体特性:
+** `begin()` 不是常数时间复杂度操作。 ** `erase(iterator)` 不返回指向下一元素的迭代器,而是返回一个代理对象,该对象可按需转换为目标迭代器;这可以避免在无需迭代器时可能产生的高昂递增操作开销。 ** 未提供用于桶管理的 API(除 `bucket_count` 外)。 ** 容器的最大负载因子由内部自动管理,用户无法手动设置。通过公开函数 `max_load` 获取的最大负载值,在高负载情况下执行删除操作时可能会降低。
+* 扁平容器( `boost::unordered_flat_set` 与 `boost::unordered_flat_map` ):
+** `value_type` 必须支持移动构造。 ** 在重哈希的过程中,指针稳定性无法保持。 ** 不提供节点提取/插入的 API 接口。
+
+== 并发容器
+
+目前 C++ 标准中尚未针对此类或任何其他类型的并发数据结构提供规范。`boost::concurrent_flat_set` / `boost::concurrent_node_set` 与 `boost::concurrent_flat_map` / `boost::concurrent_node_map` 的 API 分别参照 `std::unordered_flat_set` 和 `std::unordered_flat_map` 设计,但有一个关键区别:由于迭代器在并发场景中存在的固有问题(高竞争、易死锁),这些容器不提供迭代器。因此,Boost.Unordered 并发容器在技术上并不符合 https://en.cppreference.com/w/cpp/named_req/Container[容器^] 的模型,但它们满足 https://en.cppreference.com/w/cpp/named_req/AllocatorAwareContainer[分配器感知^] 容器(包括 https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[花式指针^] 支持)中除涉及迭代器之外的所有要求。
+
+在非并发无序容器中,迭代器主要有两项核心功能:
+
+* 访问先前通过查找定位的元素。
+* 容器遍历。
+
+为替代迭代器,Boost.Unordered 并发容器使用__内部访问__机制作为线程安全的替代方案。传统操作会返回指向容器中既有元素的迭代器(例如下列):
+
+[source,c++]
+----
+iterator find(const key_type& k);
+std::pair insert(const value_type& obj);
+----
+
+被改造为接受传递该元素的__访问函数__:
+
+[source,c++]
+----
+template size_t visit(const key_type& k, F f);
+template bool insert_or_visit(const value_type& obj, F f);
+----
+
+(第二种情况中,仅当表中存在与 `obj` 等价元素时才会调用 `f` ,而非在插入成功时调用)。容器遍历通过以下方式实现:
+
+[source,c++]
+----
+template size_t visit_all(F f);
+----
+
+在支持并行算法的 C{plus}{plus}17 编译器中提供并行化版本。通常,并发容器的接口通过将迭代器替换为访问机制的过程从非并发版本派生。对于常规映射, `iterator` 和 `const_iterator` 分别提供对元素的非常量和常量访问;此处访问权限取决于所用成员函数的常量性(同时提供 `*cvisit` 重载用于显式常量访问)。对于 `boost::concurrent_flat_set` ,访问操作始终为常量。
+
+`boost::concurrent_flat_map` / `boost::concurrent_node_map` 未提供的一个关键操作是 `operator[]` / `at` ,该功能可通过 xref:reference/concurrent_flat_map.adoc#concurrent_flat_map_try_emplace_or_cvisit[`try_emplace_or_visit`] 实现替代(该方式更为复杂)。
+
+//-
diff --git a/doc/modules/ROOT/pages/concurrent_zh_Hans.adoc b/doc/modules/ROOT/pages/concurrent_zh_Hans.adoc
new file mode 100644
index 0000000..e77b0bb
--- /dev/null
+++ b/doc/modules/ROOT/pages/concurrent_zh_Hans.adoc
@@ -0,0 +1,251 @@
+= 并发容器
+
+:idprefix: concurrent_
+
+Boost.Unordered 提供 `boost::concurrent_node_set` 、 `boost::concurrent_node_map` 、 `boost::concurrent_flat_set` 和 `boost::concurrent_flat_map` ,这些哈希表允许不同线程进行并发读写访问,无需用户实现任何同步机制。
+
+[source,c++]
+----
+std::vector input;
+boost::concurrent_flat_map m;
+
+...
+
+// process input in parallel
+const int num_threads = 8;
+std::vector threads;
+std::size_t chunk = input.size() / num_threads; // how many elements per thread
+
+for (int i = 0; i < num_threads; ++i) {
+ threads.emplace_back([&,i] {
+ // calculate the portion of input this thread takes care of
+ std::size_t start = i * chunk;
+ std::size_t end = (i == num_threads - 1)? input.size(): (i + 1) * chunk;
+
+ for (std::size_t n = start; n < end; ++n) {
+ m.emplace(input[n], calculation(input[n]));
+ }
+ });
+}
+----
+
+在上例中,线程无需同步即可访问 `m` ,这与单线程场景中的操作方式一致。在理想情况下,若将给定工作负载分配给 _N_ 个线程,其执行速度相较单线程提升 _N_ 倍——由于同步开销与__争用__的存在(某线程等待其他线程离开容器的锁定区域),实践中无法达到此理论极限。但 Boost.Unordered 并发容器设计为以极低开销运行,通常可实现__线性扩展__(即性能提升与线程数量成正比,直至达到 CPU 的逻辑核心数)。
+
+== 基于访问的 API
+
+Boost.Unordered 并发容器的新用户首先会注意到:这些类__不提供迭代器__(它们在技术层面上不符合 C{plus}{plus} 标准中的 https://en.cppreference.com/w/cpp/named_req/Container[容器] 定义)。因为迭代器本质上是线程不安全的。请参考以下假设代码:
+
+[source,c++]
+----
+auto it = m.find(k); // A: get an iterator pointing to the element with key k
+if (it != m.end() ) {
+ some_function(*it); // B: use the value of the element
+}
+----
+
+多线程场景中,若其他线程在 A 和 B 之间执行 `m.erase(k)` 操作,迭代器 `it` 可能在 B 点失效。虽然存在通过锁定指向元素来修复此问题的设计方案,但这种方法容易引发高竞争并可能导致程序死锁。 `operator++[]++` 也存在类似并发问题,因此 `boost::concurrent++_++flat++_++map` / `boost::concurrent++_++node++_++map` 也未提供该操作。替代方案是通过__访问函数__操作元素:
+
+[source,c++]
+----
+m.visit(k, [](const auto& x) { // x is the element with key k (if it exists)
+ some_function(x); // use it
+});
+----
+
+用户传递的访问函数(此处为 lambda 函数)由 Boost.Unordered 在内部以线程安全的方式执行,因此该函数可以安全访问目标元素,无需担心其他线程在此过程中造成干扰。
+
+另一方面,访问函数__无法__访问容器本身:
+
+[source,c++]
+----
+m.visit(k, [&](const auto& x) {
+ some_function(x, m.size()); // forbidden: m can't be accessed inside visitation
+});
+----
+
+但允许访问其他容器:
+
+[source,c++]
+----
+m.visit(k, [&](const auto& x) {
+ if (some_function(x)) {
+ m2.insert(x); // OK, m2 is a different boost::concurrent_flat_map
+ }
+});
+----
+
+但通常而言,访问函数应尽可能轻量以减少争用并提升并行性。在某些情况下,将繁重操作移出访问函数可能更优:
+
+[source,c++]
+----
+std::optional o;
+bool found = m.visit(k, [&](const auto& x) {
+ o = x;
+});
+if (found) {
+ some_heavy_duty_function(*o);
+}
+----
+
+访问机制在并发容器 API 中占据核心地位,许多经典操作都提供了支持访问机制的变体:
+
+[source,c++]
+----
+m.insert_or_visit(x, [](auto& y) {
+ // if insertion failed because of an equivalent element y,
+ // do something with it, for instance:
+ ++y.second; // increment the mapped part of the element
+});
+----
+
+注意此例中访问函数可__修改__元素:作为通用规则,对并发映射 `m` 的操作将根据 `m` 是否为常量类型,授予访问函数对元素的常量/非常量访问权限。 通过使用 `cvisit` 重载(如 `insert++_++or++_++cvisit` )可始终显式请求常量访问,这可能提升并行性。而并发集合的访问始终为常量访问。
+
+尽管预期使用频率较低,并发容器还提供在元素创建后立即进行访问的插入操作(除在已存在等价元素时执行常规访问之外):
+
+[source,c++]
+----
+ m.insert_and_cvisit(x,
+ [](const auto& y) {
+ std::cout<< "(" << y.first << ", " << y.second <<") inserted\n";
+ },
+ [](const auto& y) {
+ std::cout<< "(" << y.first << ", " << y.second << ") already exists\n";
+ });
+----
+
+支持访问功能的完整操作列表请参阅 xref:reference/concurrent_node_set.adoc#concurrent_node_set[`boost::concurrent++_++node++_++set`] 、 xref:reference/concurrent_node_map.adoc#concurrent_node_map[`boost::concurrent++_++node++_++map`] 、 xref:reference/concurrent_flat_set.adoc#concurrent_flat_set[`boost::concurrent++_++flat++_++set`] 和 xref:reference/concurrent_flat_map.adoc#concurrent_flat_map[`boost::concurrent++_++flat++_++map`] 的参考文档。
+
+== 全表访问
+
+在缺乏迭代器的情况下, `visit++_++all` 提供处理容器内全部元素的替代方案:
+
+[source,c++]
+----
+m.visit_all([](auto& x) {
+ x.second = 0; // reset the mapped part of the element
+});
+----
+
+在支持标准并行算法的 C{plus}{plus}17 编译器中,全表遍历访问可进行并行化处理:
+
+[source,c++]
+----
+m.visit_all(std::execution::par, [](auto& x) { // run in parallel
+ x.second = 0; // reset the mapped part of the element
+});
+----
+
+遍历过程可中途中断:
+
+[source,c++]
+----
+// finds the key to a given (unique) value
+
+int key = 0;
+int value = ...;
+bool found = !m.visit_while([&](const auto& x) {
+ if(x.second == value) {
+ key = x.first;
+ return false; // finish
+ }
+ else {
+ return true; // keep on visiting
+ }
+});
+
+if(found) { ... }
+----
+
+最后一项全表访问操作是 `erase++_++if` :
+
+[source,c++]
+----
+m.erase_if([](auto& x) {
+ return x.second == 0; // erase the elements whose mapped value is zero
+});
+----
+
+`visit++_++while` 与 `erase++_++if` 同样支持并行化。需要注意的是,为提升执行效率,全表遍历操作在运行期间不会锁定整个容器:这意味着在遍历过程中,其他线程可能同时执行元素的插入、修改或删除操作。建议在程序中避免对并发容器在任意时间点的全局状态做过强的假设。
+
+== 批量访问
+
+假设有一个 `std::array` 存储了需要在并发映射中查找的键:
+
+[source,c++]
+----
+std::array keys;
+...
+for(const auto& key: keys) {
+ m.visit(key, [](auto& x) { ++x.second; });
+}
+----
+
+__批量访问__允许用户通过单次操作传入所有键:
+
+[source,c++]
+----
+m.visit(keys.begin(), keys.end(), [](auto& x) { ++x.second; });
+----
+
+提供此功能并非仅出于语法便利性考量:通过一次性处理所有键,可应用内部优化提升性能(详见 xref:benchmarks.adoc#benchmarks_boostconcurrent_flatnode_map[基准测试])。实际上,用户可通过缓冲输入键值以实现分块批量访问,从而进一步提升效率:
+
+[source,c++]
+----
+static constexpr auto bulk_visit_size = boost::concurrent_flat_map::bulk_visit_size;
+std::array buffer;
+std::size_t i=0;
+while(...) { // processing loop
+ ...
+ buffer[i++] = k;
+ if(i == bulk_visit_size) {
+ map.visit(buffer.begin(), buffer.end(), [](auto& x) { ++x.second; });
+ i = 0;
+ }
+ ...
+}
+// flush remaining keys
+map.visit(buffer.begin(), buffer.begin() + i, [](auto& x) { ++x.second; });
+----
+
+这里存在延迟与吞吐量的权衡:缓冲机制会延长单个键的处理延迟,但每秒处理的键总数(吞吐量)会更高。 `bulk++_++visit++_++size` 是推荐的缓冲区块大小——过小的缓冲区可能导致性能下降。
+
+== 阻塞式操作
+
+并发容器可像其他 Boost.Unordered 容器一样支持复制、赋值、清空和合并操作。与大多数其他操作不同,这些属于__阻塞式操作__:在执行期间,其他线程将被阻止访问相关容器。该阻塞机制由库自动处理,用户无需采取特殊预防措施,但整体性能可能受到影响。
+
+另一阻塞操作是__重哈希__,该操作可通过 `rehash` / `reserve` 显式触发,或在插入过程中当容器负载达到 `max++_++load()` 时自动执行。与非并发容器类似,在批量插入前预先分配空间通常能加速处理过程。
+
+== 与非并发容器的互操作性
+
+由于开放寻址容器与并发容器基于相同的内部数据结构,它们可以高效地通过移动构造从其非并发对应容器转换而来,反之亦然。
+
+[caption=, title='Table {counter:table-counter}. Concurrent/non-concurrent interoperatibility']
+[cols="1,1", frame=all, grid=all]
+|===
+^|`boost::concurrent_node_set` ^|`boost::unordered_node_set`
+
+^|`boost::concurrent_node_map` ^|`boost::unordered_node_map`
+
+^|`boost::concurrent_flat_set` ^|`boost::unordered_flat_set`
+
+^|`boost::concurrent_flat_set` ^|`boost::unordered_flat_set`
+
+|===
+
+此互操作性适用于多阶段场景:部分数据处理环节需要并行执行,而其他步骤采用非并发(或只读)模式。下例中,我们需要从一个庞大的单词输入向量构建词频统计直方图:填充阶段用 `boost::concurrent++_++flat++_++map` 并行执行,随后将结果转移至最终容器。
+
+[source,c++]
+----
+std::vector words = ...;
+
+// Insert words in parallel
+boost::concurrent_flat_map m0;
+std::for_each(
+ std::execution::par, words.begin(), words.end(),
+ [&](const auto& word) {
+ m0.try_emplace_or_visit(word, 1, [](auto& x) { ++x.second; });
+ });
+
+// Transfer to a regular unordered_flat_map
+boost::unordered_flat_map m=std::move(m0);
+----
diff --git a/doc/modules/ROOT/pages/copyright_zh_Hans.adoc b/doc/modules/ROOT/pages/copyright_zh_Hans.adoc
new file mode 100644
index 0000000..527cc80
--- /dev/null
+++ b/doc/modules/ROOT/pages/copyright_zh_Hans.adoc
@@ -0,0 +1,20 @@
+[#copyright]
+= 版权与许可协议
+
+:idprefix: copyright_
+
+*丹尼尔·詹姆斯 (Daniel James)*
+
+版权所有 © 2003, 2004 杰里米·B·梅廷-谢泼德 (Jeremy B. Maitin-Shepard)
+
+版权所有 © 2005-2008 丹尼尔·詹姆斯(Daniel James)
+
+版权所有 © 2022-2025 克里斯蒂安·马扎卡斯 (Christian Mazakas)
+
+版权所有 © 2022-2025 华金·M·洛佩斯·穆尼奥斯(Joaquín M López Muñoz)
+
+版权所有 © 2022-2023 彼得·迪莫夫 (Peter Dimov)
+
+版权所有 © 2024 布雷登·加涅茨基 (Braden Ganetsky)
+
+根据Boost软件许可证1.0版分发。(详见随附文件 LICENSE++_++1++_++0.txt 或访问 http://www.boost.org/LICENSE_1_0.txt 。)
diff --git a/doc/modules/ROOT/pages/debuggability_zh_Hans.adoc b/doc/modules/ROOT/pages/debuggability_zh_Hans.adoc
new file mode 100644
index 0000000..4ab6146
--- /dev/null
+++ b/doc/modules/ROOT/pages/debuggability_zh_Hans.adoc
@@ -0,0 +1,64 @@
+[#debuggability]
+:idprefix: debuggability_
+
+= 可调试性
+
+== 调试可视化
+
+所有容器和迭代器在 Natvis 框架中均具备自定义可视化功能。
+
+=== 在项目中使用
+
+若要在项目中通过 Natvis 框架实现 Boost.Unordered 容器的可视化调试,只需将文件 link:https://github.com/boostorg/unordered/blob/develop/extra/boost_unordered.natvis[/extra/boost++_++unordered.natvis] 作为"现有项"添加到 Visual Studio 项目中即可。
+
+=== 可视化结构
+
+可视化方案与标准无序容器保持一致。容器单次最多显示 100 个元素。集合类容器中每个元素的项名称显示为 `++[++i++]++` (其中 `i` 为从 `0` 开始的显示索引)。映射元素默认显示为 `++[{++ 键值显示}++]++` ,例如当首元素为键值对 `("abc", 1)` 时,其项名称将显示为 `++[++"abc"++]++` 。用户可通过启用"ShowElementsByIndex"视图模式切换为按索引命名元素,此视图命名规则与标准无序容器保持一致。
+
+默认情况下,封闭寻址容器将显示 `++[++hash++_++function++]++` 、 `++[++key++_++eq++]++` 、适用的 `++[++spare++_++hash++_++function++]++` 与 `++[++spare++_++key++_++eq++]++` 、 `++[++allocator++]++` 以及元素列表。若启用"detailed"视图将额外显示 `++[++bucket++_++count++]++` 和 `++[++max++_++load++_++factor++]++` 信息;若启用"simple"视图,则仅显示元素列表而不包含其他条目。
+
+默认情况下,开放寻址容器显示 `++[++hash++_++function++]++` 、 `++[++key++_++eq++]++` 、 `++[++allocator++]++` 以及元素列表。若启用 "simple" 视图,则仅显示元素列表而不包含其他条目。无论采用 SIMD 还是非 SIMD 实现,均可通过 Natvis 框架进行可视化调试。
+
+迭代器显示方式与标准迭代器类似:指向元素的迭代器显示为元素值;结束迭代器显示为 `++{++ 结束迭代器 }` 。
+
+=== 花式指针
+
+分配器中使用花式指针(如 `boost::interprocess::offset++_++ptr` )时,容器可视化功能仍可正常运作。Boost.Unordered 通过 Natvis 定制点支持所有类型的花式指针。 `boost::interprocess::offset++_++ptr` 已在 Boost.Interprocess 库中预定义支持,自定义类型支持方法请参阅文件 link:https://github.com/boostorg/unordered/blob/develop/extra/boost_unordered.natvis[/extra/boost++_++unordered.natvis] 末尾注释。
+
+== GDB 美化打印器
+
+所有容器和迭代器均配备自定义 GDB 美化打印器。
+
+=== 在项目中使用
+
+使用美化打印器时,必须始终按以下方式启用美化打印功能。此项配置通常只需执行一次。
+
+```plaintext
+
+(gdb) set print pretty on
+
+```
+
+默认情况下,若编译目标为 ELF 二进制格式,生成的文件将内置 Boost.Unordered 美化打印器。要使用内嵌的美化打印器,请确保按以下方式启用自动加载功能(此操作需在每次启动 GDB 时执行,或将其添加到 ".gdbinit" 配置文件中)。
+
+```plaintext
+
+(gdb) add-auto-load-safe-path [/path/to/executable]
+
+=== 可视化结构
+
+可视化方案与标准无序容器保持一致:映射容器显示键到映射值的关联;集合容器显示从索引到值的关联关系。迭代器可显示为指向的元素内容,或标记为结束迭代器。下图展示了示例 `boost::unordered++_++map` 、示例 `boost::unordered++_++set` 及其迭代器.
+
+```plaintext
+
+(gdb) print example_unordered_map $1 = boost::unordered_map with 3 elements = {["C"] = "c", ["B"] = "b", ["A"] = "a"} (gdb) print example_unordered_map_begin $2 = iterator = { {first = "C", second = "c"} } (gdb) print example_unordered_map_end $3 = iterator = { end iterator } (gdb) print example_unordered_set $4 = boost::unordered_set with 3 elements = {[0] = "c", [1] = "b", [2] = "a"} (gdb) print example_unordered_set_begin $5 = iterator = { "c" } (gdb) print example_unordered_set_end $6 = iterator = { end iterator }
+
+```
+
+其余容器的显示逻辑完全一致,仅在显示容器本身时将其模板名称替换为对应的 "boost::unordered++_{++map++|++set}"。需要注意的事,每个子元素(即键、映射值或值)的显示均取决于其自身的打印设置,这可能包含其专属的美化打印器。
+
+无论采用 SIMD 还是非 SIMD 实现,均可通过 GDB 美化打印器查看。
+
+=== 花式指针
+
+当用户在分配器中使用花式指针(例如 `boost::interprocess::offset++_++ptr` )时,GDB 的美化打印器仍可正常工作。虽然这种情况不常见,但 Boost.Unordered 为美化打印器提供了定制点,以支持任何类型的花式指针。 `boost::interprocess::offset++_++ptr` 的支持已在Boost.Interprocess库中预先定义,自定义类型支持方法请参阅文件 link:https://github.com/boostorg/unordered/blob/develop/extra/boost_unordered_printers.py[/extra/boost++_++unordered++_++printers.py] 的末尾注释。
diff --git a/doc/modules/ROOT/pages/hash_equality_zh_Hans.adoc b/doc/modules/ROOT/pages/hash_equality_zh_Hans.adoc
new file mode 100644
index 0000000..c15a31c
--- /dev/null
+++ b/doc/modules/ROOT/pages/hash_equality_zh_Hans.adoc
@@ -0,0 +1,70 @@
+[#hash_equality]
+
+:idprefix: hash_equality_
+
+= 相等性谓词与哈希函数
+
+关联容器使用排序关系来规定元素的存储方式,而无序关联容器则依赖相等性谓词与哈希函数。例如, `xref:reference/unordered_map.adoc[boost::unordered_map]`的声明如下:
+
+```cpp template < class Key, class Mapped, class Hash = boost::hash, class Pred = std::equal_to, class Alloc = std::allocator > > class unordered_map; ```
+
+哈希函数放在首位,因为你可能只想更改哈希函数而不想更改相等谓词。例如,如果你想使用 https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash[FNV-1a 哈希^],可以这样写:
+
+```cpp boost::unordered_map dictionary; ```
+
+examples 目录中有一个链接:../../../examples/fnv1.hpp[implementation of FNV-1a^]
+
+```cpp
+
+```cpp struct iequal_to { bool operator()(std::string const& x, std::string const& y) const { return boost::algorithm::iequals(x, y, std::locale()); } };
+
+struct ihash { std::size_t operator()(std::string const& x) const { std::size_t seed = 0; std::locale locale;
+
+for(std::string::const_iterator it = x.begin(); it != x.end(); ++it) { boost::hash_combine(seed, std::toupper(*it, locale)); }
+
+return seed; } }; ```
+
+然后你可以在不区分大小写的字典中使用它:```cpp boost::unordered_map idictionary; ```
+
+这是 link:../../../examples/case_insensitive.hpp[/libs/unordered/examples/case_insensitive.hpp^] 处示例的简化版本,该示例支持其他区域设置和字符串类型。
+
+CAUTION: 在使用自定义相等谓词时,请谨慎使用相等(==)运算符
+在使用自定义相等谓词(特别是函数指针)时请务必小心。如果你用不同的相等谓词比较两个容器,结果是未定义的。对于大多数无状态函数对象而言,这种情况不可能发生——因为你只能使用相同的相等谓词来比较对象,所以两个相等谓词必然相等。但如果你使用的是函数指针或有状态的相等谓词(例如 boost::function),则可能会遇到问题。
+
+== 自定义类型
+
+类似地,自定义类型也可使用自定义哈希函数:
+
+```cpp struct point { int x; int y; };
+
+bool operator==(point const& p1, point const& p2) { return p1.x == p2.x && p1.y == p2.y; }
+
+struct point_hash { std::size_t operator()(point const& p) const { std::size_t seed = 0; boost::hash_combine(seed, p.x); boost::hash_combine(seed, p.y); return seed; } };
+
+boost::unordered_multiset points; ```
+
+由于默认哈希函数是 link:../../../../container_hash/index.html[Boost.Hash^],我们可以扩展它以支持该类型,从而无需显式给出哈希函数:
+
+```cpp struct point { int x; int y; };
+
+bool operator==(point const& p1, point const& p2) { return p1.x == p2.x && p1.y == p2.y; }
+
+std::size_t hash_value(point const& p) { std::size_t seed = 0; boost::hash_combine(seed, p.x); boost::hash_combine(seed, p.y); return seed; }
+
+// Now the default function objects work.
+boost::unordered_multiset points; ```
+
+有关如何执行此操作的更多详细信息,请参阅 link:../../../../container_hash/index.html[Boost.Hash 文档^]。请记住,它依赖于标准扩展—因此它不适用于无序关联容器的其他实现,你需要显式使用 Boost.Hash。
+
+[caption=, title='Table {counter:table-counter} Methods for accessing the hash and equality functions']
+[cols="1,.^1", frame=all, grid=rows]
+|===
+|Method |Description
+
+|`hasher hash_function() const`
+|Returns the container's hash function.
+
+|`key_equal key_eq() const`
+|Returns the container's key equality function..
+
+|===
diff --git a/doc/modules/ROOT/pages/hash_quality_zh_Hans.adoc b/doc/modules/ROOT/pages/hash_quality_zh_Hans.adoc
new file mode 100644
index 0000000..bc0648d
--- /dev/null
+++ b/doc/modules/ROOT/pages/hash_quality_zh_Hans.adoc
@@ -0,0 +1,114 @@
+[#hash_quality] = 哈希质量
+
+:idprefix: hash_quality_
+
+为了正常工作,哈希表要求提供的哈希函数具有__高质量__,这大致意味着它应尽可能均匀地使用其 `std::size++_++t` 输出空间,就像随机数生成器那样——当然,不同之处在于哈希函数的值并非随机,而是由其输入参数严格决定。
+
+Boost.Unordered 中的闭寻址容器对质量不理想的哈希函数具有较好的鲁棒性,但开放寻址和并发容器对此因素更为敏感。如果哈希函数选择不当,其性能会出现显著下降。通常,使用由 link:../../../../container_hash/index.html[Boost.Hash] 提供或生成的函数可确保质量达标,但在使用其他哈希算法时则需要特别谨慎。
+
+本节剩余的内容仅适用于开放寻址容器与并发容器。
+
+== 哈希后混合处理与雪崩效应属性
+
+即使提供的哈希函数不符合开放寻址所需的均匀分布特性,Boost.Unordered容器的性能通常仍可接受,这是因为库会执行内部__后混合处理__步骤来改善计算哈希值的统计特性。当然这会带来额外的计算开销;若希望禁用后混合处理功能,请按以下方式对哈希函数进行注解:
+
+[source,c++]
+----
+struct my_string_hash_function
+{
+ using is_avalanching = std::true_type; // instruct Boost.Unordered to not use post-mixing
+
+ std::size_t operator()(const std::string& x) const
+ {
+ ...
+ }
+};
+----
+
+通过设置 link:../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[`hash++_++is++_++avalanching`] 特征,我们告知Boost.Unordered: `my++_++string++_++hash++_++function` 具有足够高的质量,无需任何后混合处理安全网即可直接使用。但这样做的风险在于,如果哈希函数的表现未达到我们声明的理想状态,则可能导致性能下降。
+
+== 容器统计信息
+
+若在全局定义宏 `BOOST++_++UNORDERED++_++ENABLE++_++STATS` ,开放寻址容器与并发容器将计算与哈希函数质量直接相关的内部统计信息:
+
+[source,c++]
+----
+#define BOOST_UNORDERED_ENABLE_STATS
+#include
+
+...
+
+int main()
+{
+ boost::unordered_flat_map m;
+ ... // use m
+
+ auto stats = m.get_stats();
+ ... // inspect stats
+}
+----
+
+`stats` 对象提供以下统计信息:
+
+[source,subs=+quotes]
+----
+stats
+ .insertion // *Insertion operations*
+ .count // Number of operations
+ .probe_length // Probe length per operation
+ .average
+ .variance
+ .deviation
+ .successful_lookup // *Lookup operations (element found)*
+ .count // Number of operations
+ .probe_length // Probe length per operation
+ .average
+ .variance
+ .deviation
+ .num_comparisons // Elements compared per operation
+ .average
+ .variance
+ .deviation
+ .unsuccessful_lookup // *Lookup operations (element not found)*
+ .count // Number of operations
+ .probe_length // Probe length per operation
+ .average
+ .variance
+ .deviation
+ .num_comparisons // Elements compared per operation
+ .average
+ .variance
+ .deviation
+----
+
+系统维护三类内部操作的统计信息:插入操作(不考虑先前查找键是否存在的操作)、成功查找及未命中查找(包括插入元素时触发的内部查询)。__探测长度__是指每次操作所访问的 xref:structures.adoc#structures_open_addressing_containers[桶组] 数量。若哈希函数表现正常:
+
+* 平均探测长度应接近1.0。
+* 每次成功查找的平均比较次数应接近 1.0(即,
+仅检查找到的那个元素)。
+* 每次失败查找的平均比较次数应接近 0.0。
+
+提供了一个链接:../../../benchmark/string_stats.cpp[示例^],用于展示 `boost::hash`、https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash[FNV-1a 哈希^] 以及两种行为不当但被错误标记为具有雪崩效应的自定义哈希函数的容器统计信息。
+
+[listing]
+----
+ boost::unordered_flat_map: 319 ms
+ insertion: probe length 1.08771
+ successful lookup: probe length 1.06206, num comparisons 1.02121
+ unsuccessful lookup: probe length 1.12301, num comparisons 0.0388251
+
+ boost::unordered_flat_map, FNV-1a: 301 ms
+ insertion: probe length 1.09567
+ successful lookup: probe length 1.06202, num comparisons 1.0227
+ unsuccessful lookup: probe length 1.12195, num comparisons 0.040527
+
+boost::unordered_flat_map, slightly_bad_hash: 654 ms
+ insertion: probe length 1.03443
+ successful lookup: probe length 1.04137, num comparisons 6.22152
+ unsuccessful lookup: probe length 1.29334, num comparisons 11.0335
+
+ boost::unordered_flat_map, bad_hash: 12216 ms
+ insertion: probe length 699.218
+ successful lookup: probe length 590.183, num comparisons 43.4886
+ unsuccessful lookup: probe length 1361.65, num comparisons 75.238
+----
diff --git a/doc/modules/ROOT/pages/intro_zh_Hans.adoc b/doc/modules/ROOT/pages/intro_zh_Hans.adoc
new file mode 100644
index 0000000..13be990
--- /dev/null
+++ b/doc/modules/ROOT/pages/intro_zh_Hans.adoc
@@ -0,0 +1,57 @@
+[#intro]
+= 引言
+
+:idprefix: intro_ :cpp: C++
+
+https://en.wikipedia.org/wiki/Hash_table[哈希表] 是一种极其流行的计算机数据结构,几乎在所有编程语言中都能找到其不同形式的存在。红黑树(在 C{plus}{plus} 中被 `std::set` 和 `std::map` 使用)等其他关联结构在插入和查找操作上具有对数时间复杂度,但哈希表若配置得当,这些操作的平均时间复杂度可达到常数级别,并且通常速度更快。
+
+C{plus}{plus}11 标准引入了__无序关联容器__ `std::unordered++_++set` 、 `std::unordered++_++map` 、 `std::unordered++_++multiset` 和 `std::unordered++_++multimap` ,但针对哈希表的研究并未止步:CPU架构的进步(如更强大的缓存、 https://en.wikipedia.org/wiki/Single_instruction,_multiple_data[SIMD] 指令集以及日益普及的 https://en.wikipedia.org/wiki/Multi-core_processor[多核处理器])为改进基于哈希的数据结构创造了新的可能,这些新应用场景已远超 2011 年标准所定义的无序关联容器的能力范围。
+
+Boost.Unordered 提供了一系列哈希容器,它们在标准符合性、性能表现和设计应用场景上各有不同:
+
+[caption=, title='Table {counter:table-counter}. Boost.Unordered containers']
+[cols="1,1,.^1", frame=all, grid=all]
+|===
+^h| ^h|*基于节点* ^h|*扁平*
+
+^.^h|*Closed addressing* ^m| boost::unordered_set + boost::unordered_map + boost::unordered_multiset + boost::unordered_multimap ^|
+
+^.^h|*开放寻址法* ^m| boost::unordered_node_set + boost::unordered_node_map ^m| boost::unordered_flat_set + boost::unordered_flat_map
+
+^.^h|*并发* ^| `boost::concurrent_node_set` + `boost::concurrent_node_map` ^| `boost::concurrent_flat_set` + `boost::concurrent_flat_map`
+
+|===
+
+* **闭寻址容器**完全符合C{plus}{plus}无序关联容器规范,
+并在标准接口的技术约束范围内提供了业界领先的运行性能。
+* **开放寻址容器**采用了更高效的数据结构与算法
+(典型场景下性能提升2倍以上),同时为了适配实现方案而对标准接口做了细微调整。该类容器包含两种变体:*扁平式*(最快)与**基于节点式**,后者在重新哈希时能保持指针稳定性,但性能会有所下降。
+* 最后,**并发容器**专为高性能多线程场景设计与实现,
+其接口与常规C{plus}{plus}容器存在根本性差异。该系列同时提供扁平与基于节点两种变体。
+
+Boost.Unordered 中的所有 set 和 map 分别与 `std::unordered_set` 和 `std::unordered_map` 类似的方式进行实例化:
+
+[source,c++]
+----
+namespace boost {
+ template <
+ class Key,
+ class Hash = boost::hash,
+ class Pred = std::equal_to,
+ class Alloc = std::allocator >
+ class unordered_set;
+ // same for unordered_multiset, unordered_flat_set, unordered_node_set,
+ // concurrent_flat_set and concurrent_node_set
+
+ template <
+ class Key, class Mapped,
+ class Hash = boost::hash,
+ class Pred = std::equal_to,
+ class Alloc = std::allocator > >
+ class unordered_map;
+ // same for unordered_multimap, unordered_flat_map, unordered_node_map,
+ // concurrent_flat_map and concurrent_node_map
+}
+----
+
+在无序关联容器中存储对象需要同时提供键相等函数和哈希函数。标准容器中的默认函数对象支持若干基本类型,包括整数类型、浮点类型、指针类型以及标准字符串。由于 Boost.Unordered 使用 link:../../../../container_hash/index.html[boost::hash^],它还支持其他一些类型,包括标准容器。要使用这些方法不支持的任意类型,用户必须扩展 Boost.Hash 以支持该类型,或者使用自定义的相等谓词和哈希函数。更多详情请参见 xref:hash_equality.adoc#hash_equality[相等谓词与哈希函数] 一节。
diff --git a/doc/modules/ROOT/pages/rationale_zh_Hans.adoc b/doc/modules/ROOT/pages/rationale_zh_Hans.adoc
new file mode 100644
index 0000000..4f8f5d5
--- /dev/null
+++ b/doc/modules/ROOT/pages/rationale_zh_Hans.adoc
@@ -0,0 +1,79 @@
+[#rationale]
+
+:idprefix: rationale_
+
+= 实现设计依据
+
+== 闭寻址容器
+
+`boost::unordered++_[++multi++]++set` 与 `boost::unordered++_[++multi++]++map` 遵循无序关联容器的标准规范,因此其接口是确定的。但在实现层面仍需做出一些决策,其首要考量是标准符合性与跨平台移植性。
+
+关于哈希表的通用实现问题的详细综述,可参阅 http://en.wikipedia.org/wiki/Hash_table[维基百科哈希表条目] 。
+
+=== 数据结构
+
+通过制定用于访问容器桶的接口,该标准实质上要求哈希表必须采用闭寻址方案。
+
+理论上完全可以设计采用其他实现方式的哈希表。例如,采用开放寻址法,利用查找链来模拟桶的行为,但这种做法会带来一些严重问题:
+
+* 该标准要求指向元素的指针不得失效,因此
+元素无法存储在一个连续的数组中,而需要增加一层间接寻址——这将损失开放定址法的主要优势,即效率和大部分内存收益。
+* 局部迭代器的实现将极为低效,且可能无法
+满足复杂度要求。
+* 此外,标准对迭代器失效的时机也存在限制。由于
+开放寻址法在发生大量冲突时性能会急剧下降,这些限制可能会阻止必要的重新哈希操作。虽然可以通过设置较低的最大负载因子来规避此问题——但标准要求该值初始必须设为 1.0。
+* 由于该标准的制定主要着眼于闭寻址方案,
+若性能表现不符预期,将会引发用户的困惑。
+
+因此采用闭寻址方式。
+
+=== 桶数量
+
+选择哈希表桶数量有两种主流方法:一种是采用质数作为桶的数量,另一种则是使用2的幂次方。
+
+使用质数数量的桶,并通过哈希函数结果取模来选择桶,通常能获得良好的分布效果。其缺点在于所需的取模运算开销较大。这是该容器在大多数情况下之前的做法。
+
+使用2的幂次方可加快桶选择速度,但代价是牺牲哈希值的高位比特。对于一些特殊设计的哈希函数,这样做仍能获得良好效果,但由于容器需要兼容任意哈希函数,因此不能依赖这种方法。
+
+为避免此问题,可对哈希函数施加转换操作(具体示例可参阅 http://web.archive.org/web/20121102023700/http://www.concentric.net/~Ttwang/tech/inthash.htm[Thomas Wang整数哈希函数文章])。但此类变换需知晓哈希值比特数,故仅在 `size++_++t` 为64位时才会启用。
+
+自1.79.0版起,改用 https://en.wikipedia.org/wiki/Hash_function#Fibonacci_hashing[斐波那契哈希] 。在此实现中,桶编号通过公式 `(h * m) >> (w - k)` 确定:其中 `h` 为哈希值, `m` 为 `2^w` 除以黄金分割比的值, `w` 为字长(32位或64位), `2^k` 表示桶的数量。此方法在速度和分布均匀性之间实现了较好的平衡。
+
+自1.80.0版起,结合精密取模运算选用质数桶量,无需1.79.0版所用的用户哈希函数结果"混合"处理。
+
+== 开地址容器
+
+C++ 标准中对无序关联容器的规范对允许的实现方式施加了严格的限制,其中最重要的一点是隐式假定使用闭地址法。稍微放宽这一规范,则为提供能够充分利用开放寻址技术的容器变体开辟了可能性。
+
+`boost::unordered++_++flat++_++set` / `unordered++_++node++_++set` 及 `boost::unordered++_++flat++_++map` / `unordered++_++node++_++map` 的设计遵循Peter Dimov的 https://pdimov.github.io/articles/unordered_dev_plan.html[Boost.Unordered开发计划] 中提出的指导原则。下文将探讨其中最核心的设计理念。
+
+=== 哈希函数
+
+基于其丰富功能与跨平台互操作性, `boost::hash` 仍是开放寻址容器的默认哈希函数。但由于其对整型等基础类型实现的 boost::hash 缺乏开放寻址所需的统计特性,我们额外增加了后混合处理阶段:
+
+{nbsp}{nbsp}{nbsp}{nbsp} _a_ <- _h_ *mul* _C_, + {nbsp}{nbsp}{nbsp}{nbsp} _h_ <- *high*(_a_) *xor* *low*(_a_),
+
+其中 *mul* 是 _扩展乘法_(64 位架构中为 128 位,32 位环境中为 64 位),*high* 和 *low* 分别表示扩展字的高位部分和低位部分。在 64 位架构中,_C_ 是 2^64^∕https://en.wikipedia.org/wiki/Golden_ratio[_φ_] 的整数部分;而在 32 位架构中,_C_ = 0xE817FB2Du 取自 https://arxiv.org/abs/2001.05304[Steele and Vigna (2021)^]。
+
+当使用直接适合开放定址的哈希函数时,可以通过专用的 `link:../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanching[hash_is_avalanching]` 特征来退出后混合操作。针对字符串类型的 `boost::hash` 特化已被标记为雪崩式哈希。
+
+=== 平台互操作性
+
+只要不同编译器中的 `std::size_t` 大小相同,并且用户提供的哈希函数和相等谓词也具有互操作性,那么 `boost::unordered_flat_set`/`unordered_node_set` 和 `boost::unordered_flat_map`/`unordered_node_map` 的可观测行为在不同编译器之间是确定相同的——这包括对于相同的操作序列,元素的排列顺序也完全相同。
+
+尽管实现内部在可用时会使用 SIMD 技术,例如 https://en.wikipedia.org/wiki/SSE2[SSE2^] 和 https://en.wikipedia.org/wiki/ARM_architecture_family#Advanced_SIMD_(NEON)[Neon^],但这并不影响互操作性。例如,在带有 SSE2 的 x64 模式 Intel CPU 上使用 Visual Studio 的行为,与在不支持任何 SIMD 技术的 IBM s390x 上使用 GCC 的行为相同。
+
+== 并发容器
+
+Boost.Unordered 开放寻址容器所使用的相同数据结构也被选为 `boost::concurrent_flat_set`/`boost::concurrent_node_set` 和 `boost::concurrent_flat_map`/`boost::concurrent_node_map` 的基础:
+
+* 无论是在非并发环境还是并发环境下,开放寻址都比闭地址方案更快。
+并发场景中也是如此。
+* 开放寻址的内存布局极其适合在最小化锁竞争的条件下进行并发访问与修改。
+通过最小化锁定。特别是,元数据数组可用于实现查找操作,该操作在实际元素比较的最后一步之前都是无锁的。
+* 并发容器与 Boost.Unordered 扁平容器具有
+内存布局兼容性,支持其与非并发对应容器之间 xref:concurrent.adoc#concurrent_interoperability_with_non_concurrent_containers[快速双向传输] 所有元素。
+
+=== 哈希函数与平台互操作性
+
+在 xref:#rationale_hash_function[哈希函数默认值] 和 xref:#rationale_platform_interoperability[平台互操作性] 方面,并发容器与 Boost.Unordered 开放寻址容器做出了相同的决策并提供了相同的保证。
diff --git a/doc/modules/ROOT/pages/ref_zh_Hans.adoc b/doc/modules/ROOT/pages/ref_zh_Hans.adoc
new file mode 100644
index 0000000..cbd50bb
--- /dev/null
+++ b/doc/modules/ROOT/pages/ref_zh_Hans.adoc
@@ -0,0 +1,39 @@
+[#reference]
+= 参考
+
+* xref:reference/header_unordered_map_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_map_top.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_map.adoc[++++++++++++ 概要]
+* xref:reference/unordered_map.adoc[类模板 ++++++unordered_map++++++]
+* xref:reference/unordered_multimap.adoc[类模板 ++++++unordered_multimap++++++]
+* xref:reference/header_unordered_set_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_set_top.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_set.adoc[++++++++++++ 概要]
+* xref:reference/unordered_set.adoc[类模板 ++++++unordered_set++++++]
+* xref:reference/unordered_multiset.adoc[类模板 ++++++unordered_multiset++++++]
+* xref:reference/hash_traits.adoc[哈希特征]
+* xref:reference/stats.adoc[统计信息]
+* xref:reference/header_unordered_flat_map_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_flat_map.adoc[++++++++++++ 概要]
+* xref:reference/unordered_flat_map.adoc[类模板 ++++++unordered_flat_map++++++]
+* xref:reference/header_unordered_flat_set_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_flat_set.adoc[++++++++++++ 概要]
+* xref:reference/unordered_flat_set.adoc[类模板 ++++++unordered_flat_set++++++]
+* xref:reference/header_unordered_node_map_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_node_map.adoc[++++++++++++ 概要]
+* xref:reference/unordered_node_map.adoc[类模板 ++++++unordered_node_map++++++]
+* xref:reference/header_unordered_node_set_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_unordered_node_set.adoc[++++++++++++ 概要]
+* xref:reference/unordered_node_set.adoc[类模板 ++++++unordered_node_set++++++]
+* xref:reference/header_concurrent_flat_map_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_concurrent_flat_map.adoc[++++++++++++ 概要]
+* xref:reference/concurrent_flat_map.adoc[类模板 ++++++concurrent_flat_map++++++]
+* xref:reference/header_concurrent_flat_set_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_concurrent_flat_set.adoc[++++++++++++ 概要]
+* xref:reference/concurrent_flat_set.adoc[类模板 ++++++concurrent_flat_set++++++]
+* xref:reference/header_concurrent_node_map_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_concurrent_node_map.adoc[++++++++++++ 概要]
+* xref:reference/concurrent_node_map.adoc[类模板 ++++++concurrent_node_map++++++]
+* xref:reference/header_concurrent_node_set_fwd.adoc[++++++++++++ 概要]
+* xref:reference/header_concurrent_node_set.adoc[++++++++++++ 概要]
+* xref:reference/concurrent_node_set.adoc[Class Template ++++++concurrent_node_set++++++]
diff --git a/doc/modules/ROOT/pages/reference/concurrent_flat_map_zh_Hans.adoc b/doc/modules/ROOT/pages/reference/concurrent_flat_map_zh_Hans.adoc
new file mode 100644
index 0000000..7679068
--- /dev/null
+++ b/doc/modules/ROOT/pages/reference/concurrent_flat_map_zh_Hans.adoc
@@ -0,0 +1,1406 @@
+[#concurrent_flat_map]
+== 类模板 concurrent_flat_map
+
+:idprefix: concurrent_flat_map_
+
+`boost::concurrent_flat_map` — 一种哈希表,将唯一键与对应值关联,并允许在无需外部同步机制的情况下进行并发的元素插入、删除、查找和访问。
+
+尽管它充当容器的角色,boost::concurrent_flat_map 并未遵循标准 C++ 的 https://en.cppreference.com/w/cpp/named_req/Container[Container^] 概念。特别地,它不提供迭代器及相关操作(例如 begin、end 等)。元素的访问和修改是通过用户提供的 访问函数 来完成的,这些函数被传递给 concurrent_flat_map 的操作,并以受控的方式在内部执行。这种基于访问的 API 能够实现低竞争并发的使用场景。
+
+`boost::concurrent++_++flat++_++map` 的内部数据结构与 `boost::unordered++_++flat++_++map` 类似。由于采用开放寻址技术, `value++_++type` 必须支持移动构造,且在重哈希过程中无法保持指针稳定性。
+
+=== 概要
+
+[listing,subs="+macros,+quotes"]
+-----
+// #include xref:reference/header_concurrent_flat_map.adoc[``]
+
+namespace boost {
+namespace unordered {
+
+ template,
+ class Pred = std::equal_to,
+ class Allocator = std::allocator>>
+ class concurrent_flat_map {
+ public:
+ // types
+ using key_type = Key;
+ using mapped_type = T;
+ using value_type = std::pair;
+ using init_type = std::pair<
+ typename std::remove_const::type,
+ typename std::remove_const::type
+ >;
+ using hasher = Hash;
+ using key_equal = Pred;
+ using allocator_type = Allocator;
+ using pointer = typename std::allocator_traits::pointer;
+ using const_pointer = typename std::allocator_traits::const_pointer;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ using stats = xref:reference/stats.adoc#stats_stats_type[__stats-type__]; // if statistics are xref:concurrent_flat_map_boost_unordered_enable_stats[enabled]
+
+ // constants
+ static constexpr size_type xref:#concurrent_flat_map_constants[bulk_visit_size] = _implementation-defined_;
+
+ // construct/copy/destroy
+ xref:#concurrent_flat_map_default_constructor[concurrent_flat_map]();
+ explicit xref:#concurrent_flat_map_bucket_count_constructor[concurrent_flat_map](size_type n,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template
+ xref:#concurrent_flat_map_iterator_range_constructor[concurrent_flat_map](InputIterator f, InputIterator l,
+ size_type n = _implementation-defined_,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ xref:#concurrent_flat_map_copy_constructor[concurrent_flat_map](const concurrent_flat_map& other);
+ xref:#concurrent_flat_map_move_constructor[concurrent_flat_map](concurrent_flat_map&& other);
+ template
+ xref:#concurrent_flat_map_iterator_range_constructor_with_allocator[concurrent_flat_map](InputIterator f, InputIterator l,const allocator_type& a);
+ explicit xref:#concurrent_flat_map_allocator_constructor[concurrent_flat_map](const Allocator& a);
+ xref:#concurrent_flat_map_copy_constructor_with_allocator[concurrent_flat_map](const concurrent_flat_map& other, const Allocator& a);
+ xref:#concurrent_flat_map_move_constructor_with_allocator[concurrent_flat_map](concurrent_flat_map&& other, const Allocator& a);
+ xref:#concurrent_flat_map_move_constructor_from_unordered_flat_map[concurrent_flat_map](unordered_flat_map&& other);
+ xref:#concurrent_flat_map_initializer_list_constructor[concurrent_flat_map](std::initializer_list il,
+ size_type n = _implementation-defined_
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ xref:#concurrent_flat_map_bucket_count_constructor_with_allocator[concurrent_flat_map](size_type n, const allocator_type& a);
+ xref:#concurrent_flat_map_bucket_count_constructor_with_hasher_and_allocator[concurrent_flat_map](size_type n, const hasher& hf, const allocator_type& a);
+ template
+ xref:#concurrent_flat_map_iterator_range_constructor_with_bucket_count_and_allocator[concurrent_flat_map](InputIterator f, InputIterator l, size_type n,
+ const allocator_type& a);
+ template
+ xref:#concurrent_flat_map_iterator_range_constructor_with_bucket_count_and_hasher[concurrent_flat_map](InputIterator f, InputIterator l, size_type n, const hasher& hf,
+ const allocator_type& a);
+ xref:#concurrent_flat_map_initializer_list_constructor_with_allocator[concurrent_flat_map](std::initializer_list il, const allocator_type& a);
+ xref:#concurrent_flat_map_initializer_list_constructor_with_bucket_count_and_allocator[concurrent_flat_map](std::initializer_list il, size_type n,
+ const allocator_type& a);
+ xref:#concurrent_flat_map_initializer_list_constructor_with_bucket_count_and_hasher_and_allocator[concurrent_flat_map](std::initializer_list il, size_type n, const hasher& hf,
+ const allocator_type& a);
+ xref:#concurrent_flat_map_destructor[~concurrent_flat_map]();
+ concurrent_flat_map& xref:#concurrent_flat_map_copy_assignment[operator++=++](const concurrent_flat_map& other);
+ concurrent_flat_map& xref:#concurrent_flat_map_move_assignment[operator++=++](concurrent_flat_map&& other) ++noexcept(
+ (boost::allocator_traits::is_always_equal::value ||
+ boost::allocator_traits::propagate_on_container_move_assignment::value) &&
+ std::is_same::value);++
+ concurrent_flat_map& xref:#concurrent_flat_map_initializer_list_assignment[operator++=++](std::initializer_list);
+ allocator_type xref:#concurrent_flat_map_get_allocator[get_allocator]() const noexcept;
+
+
+ // visitation
+ template size_t xref:#concurrent_flat_map_cvisit[visit](const key_type& k, F f);
+ template size_t xref:#concurrent_flat_map_cvisit[visit](const key_type& k, F f) const;
+ template size_t xref:#concurrent_flat_map_cvisit[cvisit](const key_type& k, F f) const;
+ template size_t xref:#concurrent_flat_map_cvisit[visit](const K& k, F f);
+ template size_t xref:#concurrent_flat_map_cvisit[visit](const K& k, F f) const;
+ template size_t xref:#concurrent_flat_map_cvisit[cvisit](const K& k, F f) const;
+
+ template
+ size_t xref:concurrent_flat_map_bulk_visit[visit](FwdIterator first, FwdIterator last, F f);
+ template
+ size_t xref:concurrent_flat_map_bulk_visit[visit](FwdIterator first, FwdIterator last, F f) const;
+ template
+ size_t xref:concurrent_flat_map_bulk_visit[cvisit](FwdIterator first, FwdIterator last, F f) const;
+
+ template size_t xref:#concurrent_flat_map_cvisit_all[visit_all](F f);
+ template size_t xref:#concurrent_flat_map_cvisit_all[visit_all](F f) const;
+ template size_t xref:#concurrent_flat_map_cvisit_all[cvisit_all](F f) const;
+ template
+ void xref:#concurrent_flat_map_parallel_cvisit_all[visit_all](ExecutionPolicy&& policy, F f);
+ template
+ void xref:#concurrent_flat_map_parallel_cvisit_all[visit_all](ExecutionPolicy&& policy, F f) const;
+ template
+ void xref:#concurrent_flat_map_parallel_cvisit_all[cvisit_all](ExecutionPolicy&& policy, F f) const;
+
+ template bool xref:#concurrent_flat_map_cvisit_while[visit_while](F f);
+ template bool xref:#concurrent_flat_map_cvisit_while[visit_while](F f) const;
+ template bool xref:#concurrent_flat_map_cvisit_while[cvisit_while](F f) const;
+ template
+ bool xref:#concurrent_flat_map_parallel_cvisit_while[visit_while](ExecutionPolicy&& policy, F f);
+ template
+ bool xref:#concurrent_flat_map_parallel_cvisit_while[visit_while](ExecutionPolicy&& policy, F f) const;
+ template
+ bool xref:#concurrent_flat_map_parallel_cvisit_while[cvisit_while](ExecutionPolicy&& policy, F f) const;
+
+ // capacity
+ ++[[nodiscard]]++ bool xref:#concurrent_flat_map_empty[empty]() const noexcept;
+ size_type xref:#concurrent_flat_map_size[size]() const noexcept;
+ size_type xref:#concurrent_flat_map_max_size[max_size]() const noexcept;
+
+ // modifiers
+ template bool xref:#concurrent_flat_map_emplace[emplace](Args&&... args);
+ bool xref:#concurrent_flat_map_copy_insert[insert](const value_type& obj);
+ bool xref:#concurrent_flat_map_copy_insert[insert](const init_type& obj);
+ bool xref:#concurrent_flat_map_move_insert[insert](value_type&& obj);
+ bool xref:#concurrent_flat_map_move_insert[insert](init_type&& obj);
+ template size_type xref:#concurrent_flat_map_insert_iterator_range[insert](InputIterator first, InputIterator last);
+ size_type xref:#concurrent_flat_map_insert_initializer_list[insert](std::initializer_list il);
+
+ template bool xref:#concurrent_flat_map_emplace_or_cvisit[emplace_or_visit](Args&&... args, F&& f);
+ template bool xref:#concurrent_flat_map_emplace_or_cvisit[emplace_or_cvisit](Args&&... args, F&& f);
+ template bool xref:#concurrent_flat_map_copy_insert_or_cvisit[insert_or_visit](const value_type& obj, F f);
+ template bool xref:#concurrent_flat_map_copy_insert_or_cvisit[insert_or_cvisit](const value_type& obj, F f);
+ template bool xref:#concurrent_flat_map_copy_insert_or_cvisit[insert_or_visit](const init_type& obj, F f);
+ template bool xref:#concurrent_flat_map_copy_insert_or_cvisit[insert_or_cvisit](const init_type& obj, F f);
+ template bool xref:#concurrent_flat_map_move_insert_or_cvisit[insert_or_visit](value_type&& obj, F f);
+ template bool xref:#concurrent_flat_map_move_insert_or_cvisit[insert_or_cvisit](value_type&& obj, F f);
+ template bool xref:#concurrent_flat_map_move_insert_or_cvisit[insert_or_visit](init_type&& obj, F f);
+ template bool xref:#concurrent_flat_map_move_insert_or_cvisit[insert_or_cvisit](init_type&& obj, F f);
+ template
+ size_type xref:#concurrent_flat_map_insert_iterator_range_or_visit[insert_or_visit](InputIterator first, InputIterator last, F f);
+ template
+ size_type xref:#concurrent_flat_map_insert_iterator_range_or_visit[insert_or_cvisit](InputIterator first, InputIterator last, F f);
+ template size_type xref:#concurrent_flat_map_insert_initializer_list_or_visit[insert_or_visit](std::initializer_list il, F f);
+ template size_type xref:#concurrent_flat_map_insert_initializer_list_or_visit[insert_or_cvisit](std::initializer_list il, F f);
+
+ template
+ bool xref:#concurrent_flat_map_emplace_and_cvisit[emplace_and_visit](Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_map_emplace_and_cvisit[emplace_and_cvisit](Args&&... args, F1&& f1, F2&& f2);
+ template bool xref:#concurrent_flat_map_copy_insert_and_cvisit[insert_and_visit](const value_type& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_copy_insert_and_cvisit[insert_and_cvisit](const value_type& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_copy_insert_and_cvisit[insert_and_visit](const init_type& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_copy_insert_and_cvisit[insert_and_cvisit](const init_type& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_move_insert_and_cvisit[insert_and_visit](value_type&& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_move_insert_and_cvisit[insert_and_cvisit](value_type&& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_move_insert_and_cvisit[insert_and_visit](init_type&& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_map_move_insert_and_cvisit[insert_and_cvisit](init_type&& obj, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_map_insert_iterator_range_and_visit[insert_and_visit](InputIterator first, InputIterator last, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_map_insert_iterator_range_and_visit[insert_and_cvisit](InputIterator first, InputIterator last, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_map_insert_initializer_list_and_visit[insert_and_visit](std::initializer_list il, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_map_insert_initializer_list_and_visit[insert_and_cvisit](std::initializer_list il, F1 f1, F2 f2);
+
+ template bool xref:#concurrent_flat_map_try_emplace[try_emplace](const key_type& k, Args&&... args);
+ template bool xref:#concurrent_flat_map_try_emplace[try_emplace](key_type&& k, Args&&... args);
+ template bool xref:#concurrent_flat_map_try_emplace[try_emplace](K&& k, Args&&... args);
+
+ template
+ bool xref:#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_visit](const key_type& k, Args&&... args, F&& f);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_cvisit](const key_type& k, Args&&... args, F&& f);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_visit](key_type&& k, Args&&... args, F&& f);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_cvisit](key_type&& k, Args&&... args, F&& f);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_visit](K&& k, Args&&... args, F&& f);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_or_cvisit[try_emplace_or_cvisit](K&& k, Args&&... args, F&& f);
+
+ template
+ bool xref:#concurrent_flat_map_try_emplace_and_cvisit[try_emplace_and_visit](const key_type& k, Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_and_cvisit[try_emplace_and_cvisit](const key_type& k, Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_and_cvisit[try_emplace_and_visit](key_type&& k, Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_and_cvisit[try_emplace_and_cvisit](key_type&& k, Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_and_cvisit[try_emplace_and_visit](K&& k, Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_map_try_emplace_and_cvisit[try_emplace_and_cvisit](K&& k, Args&&... args, F1&& f1, F2&& f2);
+
+ template bool xref:#concurrent_flat_map_insert_or_assign[insert_or_assign](const key_type& k, M&& obj);
+ template bool xref:#concurrent_flat_map_insert_or_assign[insert_or_assign](key_type&& k, M&& obj);
+ template bool xref:#concurrent_flat_map_insert_or_assign[insert_or_assign](K&& k, M&& obj);
+
+ size_type xref:#concurrent_flat_map_erase[erase](const key_type& k);
+ template size_type xref:#concurrent_flat_map_erase[erase](const K& k);
+
+ template size_type xref:#concurrent_flat_map_erase_if_by_key[erase_if](const key_type& k, F f);
+ template size_type xref:#concurrent_flat_map_erase_if_by_key[erase_if](const K& k, F f);
+ template size_type xref:#concurrent_flat_map_erase_if[erase_if](F f);
+ template void xref:#concurrent_flat_map_parallel_erase_if[erase_if](ExecutionPolicy&& policy, F f);
+
+ void xref:#concurrent_flat_map_swap[swap](concurrent_flat_map& other)
+ noexcept(boost::allocator_traits::is_always_equal::value ||
+ boost::allocator_traits::propagate_on_container_swap::value);
+ void xref:#concurrent_flat_map_clear[clear]() noexcept;
+
+ template
+ size_type xref:#concurrent_flat_map_merge[merge](concurrent_flat_map& source);
+ template
+ size_type xref:#concurrent_flat_map_merge[merge](concurrent_flat_map&& source);
+
+ // observers
+ hasher xref:#concurrent_flat_map_hash_function[hash_function]() const;
+ key_equal xref:#concurrent_flat_map_key_eq[key_eq]() const;
+
+ // map operations
+ size_type xref:#concurrent_flat_map_count[count](const key_type& k) const;
+ template
+ size_type xref:#concurrent_flat_map_count[count](const K& k) const;
+ bool xref:#concurrent_flat_map_contains[contains](const key_type& k) const;
+ template
+ bool xref:#concurrent_flat_map_contains[contains](const K& k) const;
+
+ // bucket interface
+ size_type xref:#concurrent_flat_map_bucket_count[bucket_count]() const noexcept;
+
+ // hash policy
+ float xref:#concurrent_flat_map_load_factor[load_factor]() const noexcept;
+ float xref:#concurrent_flat_map_max_load_factor[max_load_factor]() const noexcept;
+ void xref:#concurrent_flat_map_set_max_load_factor[max_load_factor](float z);
+ size_type xref:#concurrent_flat_map_max_load[max_load]() const noexcept;
+ void xref:#concurrent_flat_map_rehash[rehash](size_type n);
+ void xref:#concurrent_flat_map_reserve[reserve](size_type n);
+
+ // statistics (if xref:concurrent_flat_map_boost_unordered_enable_stats[enabled])
+ stats xref:#concurrent_flat_map_get_stats[get_stats]() const;
+ void xref:#concurrent_flat_map_reset_stats[reset_stats]() noexcept;
+ };
+
+ // Deduction Guides
+ template>,
+ class Pred = std::equal_to>,
+ class Allocator = std::allocator>>
+ concurrent_flat_map(InputIterator, InputIterator, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type = xref:#concurrent_flat_map_deduction_guides[__see below__],
+ Hash = Hash(), Pred = Pred(), Allocator = Allocator())
+ -> concurrent_flat_map, xref:#concurrent_flat_map_iter_mapped_type[__iter-mapped-type__], Hash,
+ Pred, Allocator>;
+
+ template,
+ class Pred = std::equal_to,
+ class Allocator = std::allocator>>
+ concurrent_flat_map(std::initializer_list>,
+ typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type = xref:#concurrent_flat_map_deduction_guides[__see below__], Hash = Hash(),
+ Pred = Pred(), Allocator = Allocator())
+ -> concurrent_flat_map;
+
+ template
+ concurrent_flat_map(InputIterator, InputIterator, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type, Allocator)
+ -> concurrent_flat_map, xref:#concurrent_flat_map_iter_mapped_type[__iter-mapped-type__],
+ boost::hash>,
+ std::equal_to>, Allocator>;
+
+ template
+ concurrent_flat_map(InputIterator, InputIterator, Allocator)
+ -> concurrent_flat_map, xref:#concurrent_flat_map_iter_mapped_type[__iter-mapped-type__],
+ boost::hash>,
+ std::equal_to>, Allocator>;
+
+ template
+ concurrent_flat_map(InputIterator, InputIterator, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type, Hash,
+ Allocator)
+ -> concurrent_flat_map, xref:#concurrent_flat_map_iter_mapped_type[__iter-mapped-type__], Hash,
+ std::equal_to>, Allocator>;
+
+ template
+ concurrent_flat_map(std::initializer_list>, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type,
+ Allocator)
+ -> concurrent_flat_map, std::equal_to, Allocator>;
+
+ template
+ concurrent_flat_map(std::initializer_list>, Allocator)
+ -> concurrent_flat_map, std::equal_to, Allocator>;
+
+ template
+ concurrent_flat_map(std::initializer_list>, typename xref:#concurrent_flat_map_deduction_guides[__see below__]::size_type,
+ Hash, Allocator)
+ -> concurrent_flat_map, Allocator>;
+
+} // namespace unordered
+} // namespace boost
+-----
+
+---
+
+=== 描述
+
+*模板参数*
+
+[cols="1,1"]
+|===
+
+|_Key_
+.2+|`Key` and `T` must be https://en.cppreference.com/w/cpp/named_req/MoveConstructible[MoveConstructible^].
+`std::pair` 必须能够从任何可转换为其的 `std::pair` 对象出发,在表中进行 https://en.cppreference.com/w/cpp/named_req/EmplaceConstructible[EmplaceConstructible^] 构造,并且也必须可以从表中进行 https://en.cppreference.com/w/cpp/named_req/Erasable[Erasable^] 擦除。
+
+|_T_
+
+|_Hash_
+|A unary function object type that acts a hash function for a `Key`. It takes a single argument of type `Key` and returns a value of type `std::size_t`.
+
+|_Pred_
+|A binary function object that induces an equivalence relation on values of type `Key`. It takes two arguments of type `Key` and returns a value of type `bool`.
+
+|_Allocator_
+|An allocator whose value type is the same as the table's value type.
+支持使用https://en.cppreference.com/w/cpp/named_req/Allocator#Fancy_pointers[花式指针] 的分配器。
+
+|===
+
+容器的元素存储在内部的__桶数组__中。元素根据其哈希码被插入到对应的桶中,但如果该桶已被占用(即发生__冲突__),则会使用原始位置附近可用的桶。
+
+桶数组的大小可通过调用 `insert` / `emplace` 自动增加,也可通过调用 `rehash` / `reserve` 进行调整。容器的__负载因子__(元素数量与桶数量的比值)永远不会超过 `max++_++load++_++factor()` ,但在小规模数据情况下,实现可能允许更高的负载因子。
+
+若 link:../../../../../container_hash/doc/html/hash.html#ref_hash_is_avalanchinghash[`hash++_++is++_++avalanching`]`++<++Hash++>++::value` 为 `true` ,则直接使用哈希函数;否则,会添加一个位混合后处理阶段以提高哈希质量,但会牺牲额外的计算成本。
+
+---
+
+=== 并发要求与保证
+
+要求对同一 `Hash` 或 `Pred` 常量实例并发调用 `operator()` 时不得引入数据竞争。对于 `Alloc` (即 `Allocator` 或其重绑定后的任意分配器类型),在同一实例 `al` 上并发调用以下操作时不得引入数据竞争:
+
+* 从Alloc重新绑定后的分配器的al进行拷贝构造
+* `std::allocator_traits::allocate`
+* `std::allocator_traits::deallocate`
+* `std::allocator_traits::construct`
+* `std::allocator_traits::destroy`
+
+通常而言,若 `Hash` 、 `Pred` 和 `Allocator` 这些类型不包含状态,或其操作仅涉及对内部数据成员的常量访问,即可满足上述要求。
+
+除了析构操作外,在同一个 `concurrent_flat_map` 实例上并发调用任何操作都不会引入数据竞争——即这些操作是线程安全的。
+
+若某个操作 *op* 被显式指定为__阻塞于__ `x` (其中 `x` 为 `boost::concurrent_flat_map` 实例),则先前对 `x` 的阻塞操作将与 *op* 同步。因此,在多线程场景中,对同一 `concurrent_flat_map` 的阻塞操作将按顺序执行。
+
+若某个操作仅在触发内部重哈希时才会阻塞于 _`x`_,则称该操作阻塞于 _`x`_ 的重哈希过程。
+
+当由 `boost::concurrent_flat_map` 内部执行时,用户提供的访问函数对传入元素执行以下操作不会引入数据竞争:
+
+* 对元素的读取访问。
+* 对元素的非可变修改。
+* 对元素的可变修改:
+** 在容器接受两个访问函数的操作中,此条件始终适用于第一个访问函数。 ** 在名称不包含 `cvisit` 的非常量容器函数中,此条件适用于最后一个(或唯一一个)访问函数。
+
+任何插入或修改元素 `e` 的 `boost::concurrent_flat_map operation` 操作,都会与针对 `e` 的内部访问函数调用同步。
+
+由 `boost::concurrent_flat_map` 容器 `x` 执行的访问函数不得调用 `x` 上的任何操作;仅当对另一 `boost::concurrent_flat_map` 实例 `y` 的并发的未完成操作不直接或间接访问 `x` 时,才允许调用实例 `y` 上的操作。
+
+---
+
+=== 配置宏
+
+==== `BOOST_UNORDERED_DISABLE_REENTRANCY_CHECK`
+
+在调试版本中(更准确地说,当未定义 link:../../../../../assert/doc/html/assert.html#boost_assert_is_void[`BOOST_ASSERT_IS_VOID`] 时),系统会检测__容器重入__行为(即在访问 `m` 元素的函数内部非法调用 `m` 上的操作),并通过 `BOOST_ASSERT_MSG` 发出信号。若需关注运行时速度,可通过全局定义此宏来禁用该功能。
+
+---
+
+==== `BOOST_UNORDERED_ENABLE_STATS`
+
+全局定义此宏以启用容器的 xref:reference/stats.adoc#stats[统计计算] 功能。请注意,此选项会降低多数操作的总体性能。
+
+---
+
+=== 常量
+
+```cpp static constexpr size_type bulk_visit_size; ```
+
+xref:concurrent_flat_map_bulk_visit [批量访问] 操作内部使用的块大小。
+
+=== 构造函数
+
+==== 默认构造函数
+```c++ concurrent_flat_map(); ```
+
+使用hasher()作为哈希函数、key_equal()作为键相等谓词、allocator_type()作为分配器,构造一个空表。
+
+[horizontal]
+后置条件:size() == 0
+要求:若使用默认构造方式,则hasher、key_equal和allocator_type必须满足https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[默认可构造]要求。
+
+---
+
+==== 桶数构造函数
+```c++ explicit concurrent_flat_map(size_type n, const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); ```
+
+构造一个至少包含n个桶的空表,使用hf作为哈希函数、eql作为键相等谓词、a作为分配器。
+
+[horizontal]
+后置条件:size() == 0
+要求:若使用默认构造方式,则hasher、key_equal和allocator_type必须满足https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[默认可构造]要求。
+
+---
+
+==== 迭代器范围构造函数
+[source,c++,subs="+quotes"]
+----
+template
+ concurrent_flat_map(InputIterator f, InputIterator l,
+ size_type n = _implementation-defined_,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+----
+
+构造一个至少包含 `n` 个桶的空容器,使用 `hf` 作为哈希函数、 `eql` 作为键相等性谓词、 `a` 作为分配器,并将 `[f, l)` 范围内的元素插入其中。
+
+[horizontal]
+要求;; 若使用默认值,则 `hasher` 、 `key++_++equal` 和 `allocator++_++type` 需满足 https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造] 要求。
+
+---
+
+==== 复制构造函数
+```c++ concurrent_flat_map(concurrent_flat_map const& other); ```
+
+拷贝构造函数。复制容器内的元素、哈希函数、谓词以及分配器。
+
+若Allocator::select_on_container_copy_construction存在且签名正确,则分配器将根据其返回值构造。
+
+[horizontal]
+要求:value_type 支持复制构造。 并发特性:阻塞于 other
+
+---
+
+==== 移动构造函数
+```c++ concurrent_flat_map(concurrent_flat_map&& other); ```
+
+移动构造函数。other 的内部桶数组会直接转移到新表中。哈希函数、谓词和分配器均从 other 移动构造而来。如果启用了 xref:concurrent_flat_map_boost_unordered_enable_stats [统计功能],则从 other 转移内部统计信息,并调用 other.reset_stats()。
+
+[horizontal]
+并发特性:阻塞于 other
+
+---
+
+==== 带分配器的迭代器范围构造函数
+```c++ template concurrent_flat_map(InputIterator f, InputIterator l, const allocator_type& a); ```
+
+以a作为分配器,使用默认哈希函数与键相等谓词构造空表,并将[f, l)范围内的元素插入其中。
+
+[horizontal]
+要求:hasher、key_equal 必须满足https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[默认可构造]要求。
+
+---
+
+==== 分配器构造函数
+```c++ explicit concurrent_flat_map(Allocator const& a); ```
+
+使用分配器a构造一个空表。
+
+---
+
+==== 带分配器的复制构造函数
+```c++ concurrent_flat_map(concurrent_flat_map const& other, Allocator const& a); ```
+
+构造一个表,复制other的容器元素、哈希函数和谓词,但使用分配器a。
+
+[horizontal]
+并发特性:阻塞于 other
+
+---
+
+==== 带分配器的移动构造函数
+```c++ concurrent_flat_map(concurrent_flat_map&& other, Allocator const& a); ```
+
+若a == other.get_allocator(),则other的元素会直接转移到新表中;否则,元素从other移动构造而来。
+哈希函数与谓词从other移动构造,分配器从a拷贝构造。
+如果启用了 xref:concurrent_flat_map_boost_unordered_enable_stats [统计功能]:
+当且仅当a == other.get_allocator()时,从other转移内部统计信息
+始终调用other.reset_stats()
+
+[horizontal]
+并发特性:阻塞于 other
+
+---
+
+==== 从 unordered_flat_map 的移动构造函数
+
+```c++ concurrent_flat_map(unordered_flat_map&& other); ```
+
+从 xref:#unordered_flat_map [unordered_flat_map] 进行移动构造。other的内部桶数组会直接转移到新容器中。哈希函数、谓词和分配器均从other移动构造而来。如果启用了 xref:concurrent_flat_map_boost_unordered_enable_stats [统计功能],则从other转移内部统计信息,并调用other.reset_stats()。
+
+[horizontal]
+复杂度:O (`bucket_count()`)
+
+---
+
+==== 初始化列表构造函数
+[source,c++,subs="+quotes"]
+----
+concurrent_flat_map(std::initializer_list il,
+ size_type n = _implementation-defined_
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+----
+
+构造一个至少包含 `n` 个桶的空容器,使用 `hf` 作为哈希函数、 `eql` 作为键相等性谓词、 `a` 作为分配器,并 `il` 中的元素插入其中。
+
+[horizontal]
+要求;; 若使用默认值,则 `hasher` 、 `key++_++equal` 和 `allocator++_++type` 需满足 https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造] 要求。
+
+---
+
+==== 带分配器的桶数构造函数
+```c++ concurrent_flat_map(size_type n, allocator_type const& a); ```
+
+构造一个至少包含 n 个桶的空表,使用 hf 作为哈希函数、默认的键相等谓词,并以 a 作为分配器。
+
+[horizontal]
+后置条件:size() == 0
+要求:hasher 和 key_equal 必须满足https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[默认可构造]要求。
+
+---
+
+==== 带哈希函数和分配器的桶数构造函数
+```c++ concurrent_flat_map(size_type n, hasher const& hf, allocator_type const& a); ```
+
+构造一个至少包含 n 个桶的空表,使用 hf 作为哈希函数、默认键相等谓词,并以 a 作为分配器。
+
+[horizontal]
+后置条件:size() == 0
+要求:key_equal 必须满足https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[默认可构造]。
+
+---
+
+==== 带桶数和分配器的迭代器范围构造函数
+[source,c++,subs="+quotes"]
+----
+template
+ concurrent_flat_map(InputIterator f, InputIterator l, size_type n, const allocator_type& a);
+----
+
+构造一个至少包含 `n` 个桶的空容器,使用 `a` 作为分配器以及默认的哈希函数和键相等性谓词,并将 `++[++f, l)` 范围内的元素插入其中。
+
+[horizontal]
+要求:hasher、key_equal 必须满足https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[默认可构造]要求。
+
+---
+
+==== 带桶数和哈希函数的迭代器范围构造函数
+[source,c++,subs="+quotes"]
+----
+ template
+ concurrent_flat_map(InputIterator f, InputIterator l, size_type n, const hasher& hf,
+ const allocator_type& a);
+----
+
+构造一个至少包含 `n` 个桶的空容器,使用 `hf` 作为哈希函数、 `a` 作为分配器以及默认的键相等性谓词,并将 `[f, l)` 范围内的元素插入其中。
+
+[horizontal]
+要求;; `key++_++equal` 需满足 https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造] 要求。
+
+---
+
+==== 带分配器的初始化列表构造函数
+
+```c++ concurrent_flat_map(std::initializer_list il, const allocator_type& a); ```
+
+使用分配器a以及默认哈希函数、键相等谓词构造空表,并将il中的元素插入表中。
+
+[horizontal]
+要求:`hasher` 和 `key_equal` 需满足 https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造^] 要求。
+
+---
+
+==== 带桶数和分配器的初始化列表构造函数
+
+```c++ concurrent_flat_map(std::initializer_list il, size_type n, const allocator_type& a); ```
+
+构造一个至少包含 n 个桶的空表,使用分配器 a 以及默认哈希函数、键相等谓词,并将 il 中的元素插入表中。
+
+[horizontal]
+要求:`hasher` 和 `key_equal` 需满足 https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造^] 要求。
+
+---
+
+==== 带桶数、哈希函数和分配器的初始化列表构造函数
+
+```c++ concurrent_flat_map(std::initializer_list il, size_type n, const hasher& hf, const allocator_type& a); ```
+
+构造一个至少包含 n 个桶的空表,使用 hf 作为哈希函数、a 作为分配器、默认键相等谓词,并将 il 中的元素插入表中。
+
+[horizontal]
+要求;; `key++_++equal` 需满足 https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造] 要求。
+
+---
+
+=== 析构函数
+
+```c++
+
+[horizontal]
+备注:析构函数会作用于所有元素,且所有内存都会被释放。
+
+---
+
+=== 赋值操作
+
+==== 复制赋值
+
+```c++ concurrent_flat_map& operator=(concurrent_flat_map const& other); ```
+
+赋值运算符。销毁原有的所有元素,从other复制赋值哈希函数与谓词;若Alloc::propagate_on_container_copy_assignment存在且其值为true,则从other复制赋值分配器;最终插入other元素的副本。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/CopyInsertable[可复制插入^] 要求。并发:阻塞 `*this` 和 `other`。
+
+---
+
+==== 移动赋值
+```c++ concurrent_flat_map& operator=(concurrent_flat_map&& other) noexcept((boost::allocator_traits::is_always_equal::value || boost::allocator_traits::propagate_on_container_move_assignment::value) && std::is_same::value); ```
+移动赋值运算符。销毁当前容器原有的所有元素,交换other的哈希函数与谓词;若Alloc::propagate_on_container_move_assignment存在且其值为true,则从other移动赋值分配器。
+若此时分配器与other.get_allocator()相等,则直接转移other的内部桶数组至当前容器;否则,插入other元素的移动构造副本。
+如果启用了统计功能:
+当且仅当最终分配器与other.get_allocator()相等时,从other转移内部统计信息
+始终调用other.reset_stats()
+
+[horizontal]
+并发:阻塞于 *this 和 other。
+
+---
+
+==== 初始化列表赋值
+```c++ concurrent_flat_map& operator=(std::initializer_list il); ```
+
+并发:阻塞于 *this 和 other。
+从初始化列表赋值。销毁所有先前存在的元素。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/CopyInsertable[可复制插入^] 要求。并发:阻塞 `*this`。
+
+---
+
+=== 访问操作
+
+==== [c]visit
+
+```c++ template size_t visit(const key_type& k, F f); template size_t visit(const key_type& k, F f) const; template size_t cvisit(const key_type& k, F f) const; template size_t visit(const K& k, F f); template size_t visit(const K& k, F f) const; template size_t cvisit(const K& k, F f) const; ```
+
+若存在键与 k 等价的元素 x,则以 x 的引用调用函数 f。
+当且仅当当前容器 *this 为常量(const)时,该引用为常量引用。
+
+[horizontal]
+返回值:访问过的元素数量(0 或 1)。
+注意:template 形式的重载仅在 Hash::is_transparent 与 Pred::is_transparent 为合法成员别名时才参与重载决议。
+库假定 Hash 可同时用于 K 类型与 Key 类型,且 Pred 是透明的。
+这支持异构查找,避免了实例化 Key 类型对象带来的开销。
+
+---
+
+==== 批量访问
+
+```c++ template size_t visit(FwdIterator first, FwdIterator last, F f); template size_t visit(FwdIterator first, FwdIterator last, F f) const; template size_t cvisit(FwdIterator first, FwdIterator last, F f) const; ```
+
+对范围 [first, last) 中的每个键 k:
+如果容器中存在键与 k 等价的元素 x,则以 x 的引用调用函数 f。
+当且仅当当前容器 *this 为常量(const)时,该引用为常量引用。
+
+尽管功能上等价于对每个键单独调用 [c]visit,但批量访问因内部流线型优化,通常性能更高。
+建议 std::distance(first,last) 至少达到 bulk_visit_size 阈值时再使用,以获得性能提升;超过该大小后,性能不会进一步提升。
+
+[horizontal]
+要求:`FwdIterator` 需满足 https://en.cppreference.com/w/cpp/named_req/ForwardIterator[遗留向前迭代器^] 要求({cpp}11 至 {cpp}17),或满足 https://en.cppreference.com/w/cpp/iterator/forward_iterator[`std::forward_iterator`^] 要求({cpp}20 及更高版本)。对于 `K = std::iterator_traits::value_type`,要么 `K` 是 `key_type`,要么 `Hash::is_transparent` 和 `Pred::is_transparent` 是有效的成员 typedef。在后一种情况下,库假定 `Hash` 可同时以 `K` 和 `Key` 调用,且 `Pred` 是透明的。该机制支持异构查找,从而避免实例化 `Key` 类型的开销。返回:被访问的元素数量。
+
+---
+
+==== [c]visit_all
+
+```c++ template size_t visit_all(F f); template size_t visit_all(F f) const; template size_t cvisit_all(F f) const; ```
+
+依次以表中每个元素的引用调用函数 f。
+当且仅当当前容器 *this 为常量(const)时,该引用为常量引用。
+
+[horizontal]
+返回值:访问到的元素数量。
+
+---
+
+==== 并行 [c]visit_all
+
+```c++ template void visit_all(ExecutionPolicy&& policy, F f); template void visit_all(ExecutionPolicy&& policy, F f) const; template void cvisit_all(ExecutionPolicy&& policy, F f) const; ```
+
+以表中每个元素的引用调用函数 f。
+当且仅当当前容器 *this 为常量(const)时,该引用为常量引用。
+执行过程将根据指定的执行策略语义进行并行化。
+
+[horizontal]
+抛出异常:根据所使用执行策略的异常处理机制,如果 f 内部抛出异常,则可能会调用 std::terminate。
+注意:仅在支持 C++17 并行算法的编译器中可用。
+仅当 std::is_execution_policy_v> 为 true 时,这些重载版本才参与重载决议。
+不允许使用无序执行策略。
+
+---
+
+==== [c]visit_while
+
+```c++ template bool visit_while(F f); template bool visit_while(F f) const; template bool cvisit_while(F f) const; ```
+
+依次以表中每个元素的引用调用函数 f,直到 f 返回 false 或遍历完所有元素。
+当且仅当当前容器 *this 为常量(const)时,该元素引用为常量引用。
+
+[horizontal]
+返回值:当且仅当 f 曾返回 false 时,整体返回 false。
+
+---
+
+==== 并行 [c]visit_while
+
+```c++ template bool visit_while(ExecutionPolicy&& policy, F f); template bool visit_while(ExecutionPolicy&& policy, F f) const; template bool cvisit_while(ExecutionPolicy&& policy, F f) const; ```
+
+以表中每个元素的引用调用函数 f,直到 f 返回 false 或遍历完所有元素。
+当且仅当当前容器 *this 为常量(const)时,该元素引用为常量引用。
+执行过程将根据指定的执行策略语义进行并行化。
+
+[horizontal]
+返回值:当且仅当 f 曾返回 false 时,整体返回 false。
+抛出异常:根据所使用执行策略的异常处理机制,如果 f 内部抛出异常,则可能会调用 std::terminate。
+注意:
+仅在支持 C++17 并行算法的编译器中可用。
+仅当 std::is_execution_policy_v> 为 true 时,这些重载版本才参与重载决议。
+不允许使用无序执行策略。
+并行化意味着:即使 f 已返回 false,执行流程也不一定会立即终止;因此,f 可能还会被继续调用以处理后续元素,且这些调用同样可能返回 false。
+
+---
+
+=== 大小与容量
+
+==== 空
+
+```c++ [[nodiscard]] bool empty() const noexcept; ```
+
+[horizontal]
+返回值:size() == 0
+
+---
+
+==== 大小
+
+```c++ size_type size() const noexcept; ```
+
+[horizontal]
+返回值:表中的元素数量。
+
+[horizontal]
+注意:在存在并发插入操作时,返回的值可能无法准确反映函数执行后容器的真实大小。
+
+---
+
+==== max_size
+
+```c++ size_type max_size() const noexcept; ```
+
+[horizontal]
+返回值:容器所能容纳的最大元素数量(最大容量)。
+
+---
+
+=== 修改器
+
+==== 原地构造
+```c++ template bool emplace(Args&&... args); ```
+
+当且仅当容器中不存在等价键的元素时,才会使用参数 args 构造对象并插入到容器中。
+
+[horizontal]
+要求:`value_type` 可从 `args` 构造。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +若 `args...` 的形式为 `k,v`,则仅在确定应插入元素时才构造整个对象,检查时仅使用 `k` 参数。
+
+---
+
+==== 复制插入
+```c++ bool insert(const value_type& obj); bool insert(const init_type& obj); ```
+
+当且仅当容器中不存在等价键的元素时,才将对象 obj 插入到容器中。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/CopyInsertable[可复制插入^] 要求。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +形式为 `insert(x)` 的调用(其中 `x` 可同等转换为 `const value_type&` 和 `const init_type&`)不会产生歧义,并且会选择 `init_type` 重载。
+
+---
+
+==== 移动插入
+```c++ bool insert(value_type&& obj); bool insert(init_type&& obj); ```
+
+当且仅当容器中不存在等价键的元素时,才将对象 obj 插入到容器中。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/MoveInsertable[可移动插入^] 要求。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +形式为 `insert(x)` 的调用(其中 `x` 可同等转换为 `value_type&&` 和 `init_type&&`)不会产生歧义,并且会选择 `init_type` 重载。
+
+---
+
+==== 迭代器范围插入
+```c++ template size_type insert(InputIterator first, InputIterator last); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+ while(first != last) this->xref:#concurrent_flat_map_emplace[emplace](*first++);
+-----
+
+[horizontal]
+返回值:成功插入的元素数量。
+
+---
+
+==== 初始化列表插入
+```c++ size_type insert(std::initializer_list il); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+ this->xref:#concurrent_flat_map_insert_iterator_range[insert](il.begin(), il.end());
+-----
+
+[horizontal]
+返回值:成功插入的元素数量。
+
+---
+
+==== emplace_or_[c]visit
+```c++ template bool emplace_or_visit(Args&&... args, F&& f); template bool emplace_or_cvisit(Args&&... args, F&& f); ```
+
+若容器中无等价键的元素,则使用参数 args 构造对象并插入容器;
+否则,将等价元素的引用传递给函数 f 并调用 —— 若使用的是 emplace_or_cvisit,则该引用为常量引用。
+
+[horizontal]
+要求:`value_type` 可从 `args` 构造。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +该接口仅为展示说明,因为 C++ 不允许在变参参数包之后声明参数 `f`。
+
+---
+
+==== Copy insert_or_[c]visit
+```c++ template bool insert_or_visit(const value_type& obj, F f); template bool insert_or_cvisit(const value_type& obj, F f); template bool insert_or_visit(const init_type& obj, F f); template bool insert_or_cvisit(const init_type& obj, F f); ```
+
+当且仅当容器中不存在等价键的元素时,将对象 obj 插入容器;
+否则,将等价元素的引用传入函数 f 并调用 ——若使用的是 *_cvisit 重载版本,该引用为常量引用。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/CopyInsertable[可复制插入^] 要求。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +在形式为 `insert_or_[c]visit(obj, f)` 的调用中,接受 `const value_type&` 参数的重载仅当 `std::remove_cv::type>::type` 为 `value_type` 时才参与重载决议。
+
+---
+
+==== Move insert_or_[c]visit
+```c++ template bool insert_or_visit(value_type&& obj, F f); template bool insert_or_cvisit(value_type&& obj, F f); template bool insert_or_visit(init_type&& obj, F f); template bool insert_or_cvisit(init_type&& obj, F f); ```
+
+当且仅当容器中不存在等价键的元素时,将对象 obj 插入容器;
+否则,将等价元素的引用传入函数 f 并调用 ——若使用的是 *_cvisit 重载版本,该引用为常量引用。
+
+[horizontal]
+要求:value_type 满足 https://en.cppreference.com/w/cpp/named_req/MoveInsertable[可移动插入] 要求。
+返回值:插入成功则返回 true。
+并发:在当前对象 *this 执行重哈希期间阻塞。
+说明:触发重哈希时,会使指向元素的指针和引用失效。
+调用形式为 insert_or_[c]visit(obj, f) 时,仅当 std::remove_reference::type 类型为 value_type,接收 value_type&& 参数的重载函数才会参与重载决议。
+
+---
+
+==== 迭代器范围插入或访问
+```c++ template size_type insert_or_visit(InputIterator first, InputIterator last, F f); template size_type insert_or_cvisit(InputIterator first, InputIterator last, F f); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+ while(first != last) this->xref:#concurrent_flat_map_emplace_or_cvisit[emplace_or_[c\]visit](*first++, f);
+-----
+
+[horizontal]
+返回值:成功插入的元素数量。
+
+---
+
+==== 初始化列表插入或访问
+```c++ template size_type insert_or_visit(std::initializer_list il, F f); template size_type insert_or_cvisit(std::initializer_list il, F f); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+ this->xref:#concurrent_flat_map_insert_iterator_range_or_visit[insert_or_[c\]visit](il.begin(), il.end(), std::ref(f));
+-----
+
+[horizontal]
+返回值:成功插入的元素数量。
+
+---
+
+==== emplace_and_[c]visit
+```c++ template bool emplace_and_visit(Args&&... args, F1&& f1, F2&& f2); template bool emplace_and_cvisit(Args&&... args, F1&& f1, F2&& f2); ```
+
+若容器中无等价键的元素,则使用参数args构造对象并插入容器,随后以新创建元素的非常量引用调用f1;
+否则,以等价元素的引用调用f2;若使用emplace_and_cvisit,则该引用为常量引用。
+
+[horizontal]
+要求:`value_type` 可从 `args` 构造。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +该接口仅为展示说明,因为 C++ 不允许在变参参数包之后声明参数 `f1` 和 `f2`。
+
+---
+
+==== 复制 insert_and_[c]visit
+```c++ template bool insert_and_visit(const value_type& obj, F1 f1, F2 f2); template bool insert_and_cvisit(const value_type& obj, F1 f1, F2 f2); template bool insert_and_visit(const init_type& obj, F1 f1, F2 f2); template bool insert_and_cvisit(const init_type& obj, F1 f1, F2 f2); ```
+
+当且仅当容器中不存在等价键的元素时,插入obj,随后以新创建元素的非常量引用调用f1;
+否则,以等价元素的引用调用f2;若使用*_cvisit重载版本,则该引用为常量引用。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/CopyInsertable[可复制插入^] 要求。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +在形式为 `insert_and_[c]visit(obj, f1, f2)` 的调用中,接受 `const value_type&` 参数的重载仅当 `std::remove_cv::type>::type` 为 `value_type` 时才参与重载决议。
+
+---
+
+==== 移动 insert_and_[c]visit
+```c++ template bool insert_and_visit(value_type&& obj, F1 f1, F2 f2); template bool insert_and_cvisit(value_type&& obj, F1 f1, F2 f2); template bool insert_and_visit(init_type&& obj, F1 f1, F2 f2); template bool insert_and_cvisit(init_type&& obj, F1 f1, F2 f2); ```
+
+当且仅当容器中不存在等价键的元素时,插入obj,随后以新创建元素的非常量引用调用f1;
+否则,以等价元素的引用调用f2;若使用*_cvisit重载版本,则该引用为常量引用。
+
+[horizontal]
+要求:`value_type` 需满足 https://en.cppreference.com/w/cpp/named_req/MoveInsertable[可移动插入^] 要求。返回:若执行了插入则返回 `true`。并发:在 `*this` 的 rehash 操作上阻塞。注意:如果执行了 rehash,则指向元素的指针和引用会失效。+ +在形式为 `insert_and_[c]visit(obj, f1, f2)` 的调用中,接受 `value_type&&` 参数的重载仅当 `std::remove_reference::type` 为 `value_type` 时才参与重载决议。
+
+---
+
+==== 迭代器范围插入并访问
+```c++ template size_type insert_or_visit(InputIterator first, InputIterator last, F1 f1, F2 f2); template size_type insert_or_cvisit(InputIterator first, InputIterator last, F1 f1, F2 f2); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+ while(first != last) this->xref:#concurrent_flat_map_emplace_and_cvisit[emplace_and_[c\]visit](*first++, f1, f2);
+-----
+
+[horizontal]
+返回值:成功插入的元素数量。
+
+---
+
+==== 初始化列表插入并访问
+```c++ template size_type insert_and_visit(std::initializer_list il, F1 f1, F2 f2); template size_type insert_and_cvisit(std::initializer_list il, F1 f1, F2 f2); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+ this->xref:#concurrent_flat_map_insert_iterator_range_and_visit[insert_and_[c\]visit](il.begin(), il.end(), std::ref(f1), std::ref(f2));
+-----
+
+[horizontal]
+返回值:成功插入的元素数量。
+
+---
+
+==== try_emplace
+```c++ template bool try_emplace(const key_type& k, Args&&... args); template bool try_emplace(key_type&& k, Args&&... args); template bool try_emplace(K&& k, Args&&... args); ```
+
+若容器中不存在键为k的元素,则将由k和args构造的元素插入容器。
+
+[horizontal]
+返回值:插入成功则返回true。
+并发:对当前对象*this进行重哈希时阻塞。
+说明:该函数与 xref:#concurrent_flat_map_emplace [emplace] 类似,区别在于若存在等价键的元素,则不会构造value_type;否则,构造形式为:
+// first two overloads
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...))
+
+// third overload
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...)) ```
+
+这与 xref:#concurrent_flat_map_emplace [emplace] 不同,后者仅将所有参数转发给value_type的构造函数。
+
+Invalidates pointers and references to elements if a rehashing is issued.
+
+若`Hash::is_transparent`与`Pred::is_transparent`为合法的成员类型别名,则`template`重载版本才会参与重载决议。库假定`Hash`可同时接收`K`与`Key`类型参数调用,且`Pred`为透明比较器。该设计支持异构查找,避免了实例化`Key`类型对象的开销。
+
+--
+
+---
+
+==== try_emplace_or_[c]visit
+```c++ template bool try_emplace_or_visit(const key_type& k, Args&&... args, F&& f); template bool try_emplace_or_cvisit(const key_type& k, Args&&... args, F&& f); template bool try_emplace_or_visit(key_type&& k, Args&&... args, F&& f); template bool try_emplace_or_cvisit(key_type&& k, Args&&... args, F&& f); template bool try_emplace_or_visit(K&& k, Args&&... args, F&& f); template bool try_emplace_or_cvisit(K&& k, Args&&... args, F&& f); ```
+
+若容器中不存在键为`k`的元素,则将由`k`和`args`构造的元素插入容器。否则,以等价元素的引用调用`f`;若使用`*_cvisit`重载版本,则该引用为常量引用。
+
+[horizontal]
+返回值:插入成功则返回true。
+并发:对当前对象*this进行重哈希时阻塞。
+说明:若存在等价键的元素,则不会构造value_type;否则,构造形式为:
+// first four overloads
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...))
+
+// last two overloads
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...)) ```
+
+Invalidates pointers and references to elements if a rehashing is issued.
+
+该接口仅为说明性用途,因为C++不允许在可变参数包之后声明参数`f`。
+
+若`Hash::is_transparent`和`Pred::is_transparent`是有效的成员类型别名,则`template`重载版本才会参与重载决议。库假定`Hash`可同时接受`K`与`Key`类型的参数调用,且`Pred`是透明的。这支持异构查找,避免了实例化`Key`类型对象的开销。
+
+--
+
+---
+
+==== try_emplace_and_[c]visit
+```c++ template bool try_emplace_and_visit(const key_type& k, Args&&... args, F1&& f1, F2&& f2); template bool try_emplace_and_cvisit(const key_type& k, Args&&... args, F1&& f1, F2&& f2); template bool try_emplace_and_visit(key_type&& k, Args&&... args, F1&& f1, F2&& f2); template bool try_emplace_and_cvisit(key_type&& k, Args&&... args, F1&& f1, F2&& f2); template bool try_emplace_and_visit(K&& k, Args&&... args, F1&& f1, F2&& f2); template bool try_emplace_and_cvisit(K&& k, Args&&... args, F1&& f1, F2&& f2); ```
+
+若容器中不存在键为`k`的元素,则将由`k`和`args`构造的元素插入容器,随后以新创建元素的非常量引用调用`f1`;
+否则,以等价元素的引用调用`f2`;若使用`*_cvisit`重载版本,则该引用为常量引用。
+
+[horizontal]
+返回值:插入成功则返回true。
+并发:对当前对象*this进行重哈希时阻塞。
+说明:若存在等价键的元素,则不会构造value_type;否则,构造形式为:
+// first four overloads
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...))
+
+// last two overloads
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(args)...)) ```
+
+Invalidates pointers and references to elements if a rehashing is issued.
+
+该接口仅为说明性用途,因为C++不允许在可变参数包之后声明`f1`和`f2`参数。
+
+若`Hash::is_transparent`和`Pred::is_transparent`是有效的成员类型别名,则`template`重载版本才会参与重载决议。库假定`Hash`可同时接受`K`与`Key`类型的参数调用,且`Pred`是透明的。这支持异构查找,避免了实例化`Key`类型对象的开销。
+
+--
+
+---
+
+==== insert_or_assign
+```c++ template bool insert_or_assign(const key_type& k, M&& obj); template bool insert_or_assign(key_type&& k, M&& obj); template bool insert_or_assign(K&& k, M&& obj); ```
+
+向容器插入新元素,或通过赋值给容器内已存值来更新现有元素。
+
+若容器中存在键为`k`的元素,则通过`std::forward(obj)`赋值来更新该元素。
+
+若不存在该元素,则将其以如下形式添加到容器中:
+// first two overloads
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(obj)))
+
+// third overload
+value_type(std::piecewise_construct, std::forward_as_tuple(std::forward(k)), std::forward_as_tuple(std::forward(obj))) ```
+
+[horizontal]
+返回值:插入成功时返回`true`。
+并发:执行重哈希操作时会阻塞当前对象`*this`。
+说明:若触发重哈希,将使指向元素的指针和引用失效。
+`template` 仅当 `Hash::is_transparent` 和 `Pred::is_transparent` 为有效成员类型别名时才参与重载决议。库假定`Hash`可同时接受`K`与`Key`类型参数调用,且`Pred`是透明的。这支持异构查找,避免了实例化`Key`类型对象的开销。
+
+---
+
+==== 擦除
+```c++ size_type erase(const key_type& k); template size_type erase(const K& k); ```
+
+若存在键等价于`k`的元素,则删除该元素。
+
+[horizontal]
+返回值:删除的元素数量(0 或 1)。
+异常:仅当哈希函数`hasher`或键比较函数`key_equal`抛出异常时才会抛出异常。
+说明:仅当`Hash::is_transparent`和`Pred::is_transparent`为有效的成员类型别名时,`template`重载版本才参与重载决议。库假定`Hash`可同时接受`K`与`Key`类型的参数调用,且`Pred`是透明的。该设计支持异构查找,避免了实例化`Key`类型对象的开销。
+
+---
+
+==== erase_if by Key
+```c++ template size_type erase_if(const key_type& k, F f); template size_type erase_if(const K& k, F f); ```
+
+若存在键与 `k` 等价的元素 `x`,且 `f(x)` 返回 `true`,则删除该元素。
+
+[horizontal]
+返回值:删除的元素数量(0 或 1)。
+异常:仅当哈希函数`hasher`、键比较函数`key_equal`或函数`f`抛出异常时才会抛出异常。
+说明:`f`接收元素`x`的非常量引用。
+
+仅当`std::is_execution_policy_v>`为`false`时,`template`重载版本才参与重载决议。
+
+仅当`Hash::is_transparent`和`Pred::is_transparent`为有效的成员类型别名时,`template`重载版本才参与重载决议。库假定`Hash`可同时接受`K`与`Key`类型的参数调用,且`Pred`是透明的。该设计支持异构查找,避免了实例化`Key`类型对象的开销。
+
+---
+
+==== erase_if
+```c++ template size_type erase_if(F f); ```
+
+依次以非常量引用为参数,对容器中的每个元素调用`f`,并删除所有`f`返回`true`的元素。
+
+[horizontal]
+返回值:被删除的元素数量。
+异常:仅当函数 `f` 抛出异常时才会抛出异常。
+
+---
+
+==== 并行条件擦除
+```c++ template void erase_if(ExecutionPolicy&& policy, F f); ```
+
+依次以非常量引用为参数,对容器中的每个元素调用`f`,并删除所有`f`返回`true`的元素。执行过程将根据指定的执行策略语义进行并行化处理。
+
+[horizontal]
+异常:根据所使用执行策略的异常处理机制,若`f`内部抛出异常,可能会调用`std::terminate`终止程序。
+说明:仅在支持C++17并行算法的编译器中可用。
+
+仅当`std::is_execution_policy_v>`为`true`时,该重载版本参与重载决议。
+
+不允许使用无顺序执行策略。
+
+---
+
+==== 交换
+```c++ void swap(concurrent_flat_map& other) noexcept(boost::allocator_traits::is_always_equal::value || boost::allocator_traits::propagate_on_container_swap::value); ```
+
+将当前容器的内容与参数容器进行交换。
+
+若`Allocator::propagate_on_container_swap`已定义且其值为`true`,则交换两个容器的分配器;否则,使用不相等的分配器进行交换会导致未定义行为。
+
+[horizontal]
+异常:除非`key_equal`或`hasher`在交换时抛出异常,否则不抛出任何异常。并发:会阻塞当前对象`*this`和参数对象`other`。
+
+---
+
+==== 清空
+```c++ void clear() noexcept; ```
+
+清空容器中的所有元素。
+
+[horizontal]
+后置条件:容器大小 `size() == 0`,且 `max_load() >= max_load_factor() * bucket_count()`
+并发:会阻塞当前对象 `*this`。
+
+---
+
+==== 合并
+```c++ template size_type merge(concurrent_flat_map& source); template size_type merge(concurrent_flat_map&& source); ```
+
+将来源容器`source`中所有**键不存在于当前容器`*this`**中的元素**移动插入**到当前容器,并从`source`中擦除这些元素。
+
+[horizontal]
+返回值:插入的元素数量。
+并发:会阻塞当前对象 `*this` 和源对象 `source`。
+
+---
+
+=== 观察器
+
+==== get_allocator
+``` allocator_type get_allocator() const noexcept; ```
+
+[horizontal]
+返回值:容器的分配器。
+
+---
+
+==== 哈希函数
+``` hasher hash_function() const; ```
+
+[horizontal]
+返回值:容器的哈希函数。
+
+---
+
+==== key_eq
+``` key_equal key_eq() const; ```
+
+[horizontal]
+返回值:容器的键相等性谓词。
+
+---
+
+=== 映射操作
+
+==== count
+```c++ size_type count(const key_type& k) const; template size_type count(const K& k) const; ```
+
+[horizontal]
+返回值:匹配键 `k` 的元素数量(0 或 1)。
+说明:仅当 `Hash::is_transparent` 和 `Pred::is_transparent` 为有效成员类型别名时,`template` 重载版本才参与重载决议。库假定哈希函数可同时作用于 `K` 类型与键类型,且相等谓词是透明的,从而支持异构查找,避免实例化键类型带来的开销。
+
+若存在并发插入操作,返回值可能无法精确反映容器执行后的真实状态。
+
+---
+
+==== 包含
+```c++ bool contains(const key_type& k) const; template bool contains(const K& k) const; ```
+
+[horizontal]
+返回值:布尔值,表示容器中是否存在键等于 `k` 的元素。
+说明:仅当 `Hash::is_transparent` 和 `Pred::is_transparent` 为有效成员类型别名时,`template` 重载版本才参与重载决议。库假定哈希函数可同时作用于 `K` 类型与键类型,且相等谓词是透明的,从而支持异构查找,避免实例化键类型带来的开销。
+
+若存在并发插入操作,返回值可能无法精确反映容器执行后的真实状态。
+
+---
+=== 桶接口
+
+==== bucket_count
+```c++ size_type bucket_count() const noexcept; ```
+
+[horizontal]
+返回值:桶数组的大小。
+
+---
+
+=== 哈希策略
+
+==== 负载因子
+```c++ float load_factor() const noexcept; ```
+
+[horizontal]
+返回值:`static_cast(size())/static_cast(bucket_count())`;若 `bucket_count() == 0`,则返回 `0`。
+
+---
+
+==== max_load_factor(最大负载因子)
+
+```c++ float max_load_factor() const noexcept; ```
+
+[horizontal]
+返回值:容器的最大负载因子。
+
+---
+
+==== 设置最大负载因子
+```c++ void max_load_factor(float z); ```
+
+[horizontal]
+效果:无任何操作,用户不允许修改此参数。保留该函数是为了与 `boost::unordered_map` 保持兼容。
+
+---
+
+
+==== max_load(最大负载)
+
+```c++ size_type max_load() const noexcept; ```
+
+[horizontal]
+返回值:容器在不进行重哈希的前提下可容纳的最大元素数量(假定不会再擦除任何元素)。
+说明:容器在构造、重哈希或清空后,其最大负载量至少为 `max_load_factor() * bucket_count()`。在高负载条件下执行擦除操作时,该数值可能会降低。
+若存在并发插入操作,返回值可能无法精确反映容器执行后的真实状态。
+
+---
+
+==== 重哈希
+```c++ void rehash(size_type n); ```
+
+效果:必要时调整桶数组的大小,使桶数量至少为 `n`,且负载因子小于等于最大负载因子。
+适用场景下,该操作会**增大或缩小**容器的桶数量 `bucket_count()`。
+
+当容器大小 `size() == 0` 时,调用 `rehash(0)` 会**释放底层的桶数组内存**。
+
+会使指向元素的指针和引用失效,并改变元素的存储顺序。
+
+[horizontal]
+异常:若抛出异常,函数无任何效果(由容器的哈希函数或比较函数抛出的异常除外)。
+并发:阻塞当前对象 `*this`。
+
+==== 保留
+```c++ void reserve(size_type n); ```
+
+等价于 `a.rehash(ceil(n / a.max_load_factor()))`。
+
+与 `rehash` 功能类似,该函数可用于**增大或缩小**容器的桶数量。
+
+会使指向元素的指针和引用失效,并改变元素的存储顺序。
+
+[horizontal]
+异常:若抛出异常,函数无任何效果(由容器的哈希函数或比较函数抛出的异常除外)。
+并发:阻塞当前对象 `*this`。
+
+---
+
+=== 统计信息
+
+==== get_stats
+```c++ stats get_stats() const; ```
+
+[horizontal]
+返回值:容器截至目前执行的插入与查找操作的统计描述信息。
+说明:仅当**启用统计计算**时,该函数才可用。
+
+---
+
+==== reset_stats
+```c++ void reset_stats() noexcept; ```
+
+[horizontal]
+效果:将容器维护的内部统计数据归零。
+说明:仅当**启用统计计算**时,该函数才可用。
+
+---
+
+=== 推导指引
+满足以下任一条件时,推导指引不参与重载决议:
+
+- 该推导指引包含 `InputIterator` 模板参数,且为此参数推导出的类型不符合输入迭代器的要求。 - 该推导指引包含 `Allocator` 模板参数,且为该参数推导出的类型不符合分配器要求。 - 该推导指引包含 `Hash` 模板参数,且为该参数推导出的类型为整型或符合分配器要求。 - 该推导指引包含 `Pred` 模板参数,且为该参数推导出的类型符合分配器要求。
+
+推导指引中的 `size++_++type` 参数类型,指向由该推导指引所推导容器类型的 `size++_++type` 成员类型。其默认值与所选构造函数的默认值一致。
+
+==== _iter-value-type_
+[listings,subs="+macros,+quotes"]
+-----
+template
+ using __iter-value-type__ =
+ typename std::iterator_traits::value_type; // exposition only
+-----
+
+==== __iter-key-type__
+[listings,subs="+macros,+quotes"]
+-----
+template
+ using __iter-key-type__ = std::remove_const_t<
+ std::tuple_element_t<0, xref:#concurrent_flat_map_iter_value_type[__iter-value-type__]>>; // exposition only
+-----
+
+==== __iter-mapped-type__
+[listings,subs="+macros,+quotes"]
+-----
+template
+ using __iter-mapped-type__ =
+ std::tuple_element_t<1, xref:#concurrent_flat_map_iter_value_type[__iter-value-type__]>; // exposition only
+-----
+
+==== __iter-to-alloc-type__
+[listings,subs="+macros,+quotes"]
+-----
+template
+ using __iter-to-alloc-type__ = std::pair<
+ std::add_const_t>>,
+ std::tuple_element_t<1, xref:#concurrent_flat_map_iter_value_type[__iter-value-type__]>>; // exposition only
+-----
+
+=== 相等性比较
+
+==== operator
+```c++ template bool operator==(const concurrent_flat_map& x, const concurrent_flat_map& y); ```
+
+若 `x.size() == y.size()`,且对于 `x` 中的每个元素,`y` 中均存在拥有相同键、值相等(使用 `operator==` 比较值类型)的元素,则返回 `true`。
+
+[horizontal]
+并发:阻塞 `x` 和 `y`。
+说明:若两个容器的相等判断谓词不一致,行为未定义。
+
+---
+
+==== operator!
+```c++ template bool operator!=(const concurrent_flat_map& x, const concurrent_flat_map& y); ```
+
+若`x.size() == y.size()`,且`x`中每个元素在`y`中都存在键相同、值相等(使用`operator==`比较值类型)的元素,则返回`false`。
+
+[horizontal]
+并发:阻塞 `x` 和 `y`。
+说明:若两个容器的相等判断谓词不一致,行为未定义。
+
+---
+
+=== 交换
+```c++ template void swap(concurrent_flat_map& x, concurrent_flat_map& y) noexcept(noexcept(x.swap(y))); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+x.xref:#concurrent_flat_map_swap[swap](y);
+-----
+
+---
+
+=== erase_if
+```c++ template typename concurrent_flat_map::size_type erase_if(concurrent_flat_map& c, Predicate pred); ```
+
+等效于 [listing,subs="+macros,+quotes"]
+-----
+c.xref:#concurrent_flat_map_erase_if[erase_if](pred);
+-----
+
+=== 序列化
+
+`concurrent++_++flat++_++map` 可通过本组件库提供的 API,借助 link:../../../../../serialization/index.html[Boost.Serialization] 进行归档/检索。支持常规归档与 XML 归档两种格式。
+
+==== 将concurrent++_++flat++_++map保存到归档
+
+将 `concurrent++_++flat++_++map` 容器 `x` 的所有元素保存到归档(XML归档) `ar` 中。
+
+[horizontal]
+要求:`std::remove_const::type` 和 `std::remove_const::type` 必须是可序列化的(支持 XML 序列化),并且它们支持 Boost.Serialization 的 `save_construct_data` / `load_construct_data` 协议(https://en.cppreference.com/w/cpp/named_req/DefaultConstructible[可默认构造^] 类型自动支持该协议)。并发:阻塞 `x`。
+
+---
+
+==== 从归档加载concurrent++_++flat++_++map
+
+删除 `concurrent++_++flat++_++map` 容器 `x` 中所有已存在的元素,并从归档(XML 归档) `ar` 中插入原始 `concurrent++_++flat++_++map` 容器 `other` 的元素副本,这些副本是从 `ar` 所读取的存储中恢复的。
+
+[horizontal]
+要求;; `x.key++_++equal()` 需要在功能上等价于 `other.key++_++equal()` 。 并发性;; 阻塞于 `x` 。
diff --git a/doc/modules/ROOT/pages/reference/concurrent_flat_set_zh_Hans.adoc b/doc/modules/ROOT/pages/reference/concurrent_flat_set_zh_Hans.adoc
new file mode 100644
index 0000000..d7f4983
--- /dev/null
+++ b/doc/modules/ROOT/pages/reference/concurrent_flat_set_zh_Hans.adoc
@@ -0,0 +1,1272 @@
+[#concurrent_flat_set]
+== 类模板 concurrent++_++flat++_++set
+
+:idprefix: concurrent_flat_set_
+
+`boost::concurrent++_++flat++_++set` —— 一种存储唯一值的哈希表,它支持并发的元素插入、删除、查找及访问操作,且无需外部同步机制。
+
+尽管 `boost::concurrent++_++flat++_++set` 具备容器特性,但它并不符合 C{plus}{plus}标准中的 https://en.cppreference.com/w/cpp/named_req/Container[容器] 概念。具体而言,该容器未提供迭代器及相关操作(如 `begin` 、 `end` 等)。元素访问通过用户提供的__访问函数__实现,这些函数被传递至 `concurrent++_++flat++_++set` 操作中,并在其内部以受控方式执行。这种基于访问机制的 API 设计能够有效支持低争用的并发应用场景。
+
+`boost::concurrent++_++flat++_++set` 的内部数据结构类似于 `boost::unordered++_++flat++_++set` 。由于其采用开放寻址技术, `value++_++type` 必须满足可移动构造要求,且在重哈希过程中无法保持指针稳定性。
+
+=== 概要
+
+[listing,subs="+macros,+quotes"]
+-----
+// #include xref:reference/header_concurrent_flat_set.adoc[``]
+
+namespace boost {
+namespace unordered {
+
+ template,
+ class Pred = std::equal_to,
+ class Allocator = std::allocator>
+ class concurrent_flat_set {
+ public:
+ // types
+ using key_type = Key;
+ using value_type = Key;
+ using init_type = Key;
+ using hasher = Hash;
+ using key_equal = Pred;
+ using allocator_type = Allocator;
+ using pointer = typename std::allocator_traits::pointer;
+ using const_pointer = typename std::allocator_traits::const_pointer;
+ using reference = value_type&;
+ using const_reference = const value_type&;
+ using size_type = std::size_t;
+ using difference_type = std::ptrdiff_t;
+
+ using stats = xref:reference/stats.adoc#stats_stats_type[__stats-type__]; // if statistics are xref:concurrent_flat_set_boost_unordered_enable_stats[enabled]
+
+ // constants
+ static constexpr size_type xref:#concurrent_flat_set_constants[bulk_visit_size] = _implementation-defined_;
+
+ // construct/copy/destroy
+ xref:#concurrent_flat_set_default_constructor[concurrent_flat_set]();
+ explicit xref:#concurrent_flat_set_bucket_count_constructor[concurrent_flat_set](size_type n,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ template
+ xref:#concurrent_flat_set_iterator_range_constructor[concurrent_flat_set](InputIterator f, InputIterator l,
+ size_type n = _implementation-defined_,
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ xref:#concurrent_flat_set_copy_constructor[concurrent_flat_set](const concurrent_flat_set& other);
+ xref:#concurrent_flat_set_move_constructor[concurrent_flat_set](concurrent_flat_set&& other);
+ template
+ xref:#concurrent_flat_set_iterator_range_constructor_with_allocator[concurrent_flat_set](InputIterator f, InputIterator l,const allocator_type& a);
+ explicit xref:#concurrent_flat_set_allocator_constructor[concurrent_flat_set](const Allocator& a);
+ xref:#concurrent_flat_set_copy_constructor_with_allocator[concurrent_flat_set](const concurrent_flat_set& other, const Allocator& a);
+ xref:#concurrent_flat_set_move_constructor_with_allocator[concurrent_flat_set](concurrent_flat_set&& other, const Allocator& a);
+ xref:#concurrent_flat_set_move_constructor_from_unordered_flat_set[concurrent_flat_set](unordered_flat_set&& other);
+ xref:#concurrent_flat_set_initializer_list_constructor[concurrent_flat_set](std::initializer_list il,
+ size_type n = _implementation-defined_
+ const hasher& hf = hasher(),
+ const key_equal& eql = key_equal(),
+ const allocator_type& a = allocator_type());
+ xref:#concurrent_flat_set_bucket_count_constructor_with_allocator[concurrent_flat_set](size_type n, const allocator_type& a);
+ xref:#concurrent_flat_set_bucket_count_constructor_with_hasher_and_allocator[concurrent_flat_set](size_type n, const hasher& hf, const allocator_type& a);
+ template
+ xref:#concurrent_flat_set_iterator_range_constructor_with_bucket_count_and_allocator[concurrent_flat_set](InputIterator f, InputIterator l, size_type n,
+ const allocator_type& a);
+ template
+ xref:#concurrent_flat_set_iterator_range_constructor_with_bucket_count_and_hasher[concurrent_flat_set](InputIterator f, InputIterator l, size_type n, const hasher& hf,
+ const allocator_type& a);
+ xref:#concurrent_flat_set_initializer_list_constructor_with_allocator[concurrent_flat_set](std::initializer_list il, const allocator_type& a);
+ xref:#concurrent_flat_set_initializer_list_constructor_with_bucket_count_and_allocator[concurrent_flat_set](std::initializer_list il, size_type n,
+ const allocator_type& a);
+ xref:#concurrent_flat_set_initializer_list_constructor_with_bucket_count_and_hasher_and_allocator[concurrent_flat_set](std::initializer_list il, size_type n, const hasher& hf,
+ const allocator_type& a);
+ xref:#concurrent_flat_set_destructor[~concurrent_flat_set]();
+ concurrent_flat_set& xref:#concurrent_flat_set_copy_assignment[operator++=++](const concurrent_flat_set& other);
+ concurrent_flat_set& xref:#concurrent_flat_set_move_assignment[operator++=++](concurrent_flat_set&& other)
+ noexcept(boost::allocator_traits::is_always_equal::value ||
+ boost::allocator_traits::propagate_on_container_move_assignment::value);
+ concurrent_flat_set& xref:#concurrent_flat_set_initializer_list_assignment[operator++=++](std::initializer_list);
+ allocator_type xref:#concurrent_flat_set_get_allocator[get_allocator]() const noexcept;
+
+
+ // visitation
+ template size_t xref:#concurrent_flat_set_cvisit[visit](const key_type& k, F f);
+ template size_t xref:#concurrent_flat_set_cvisit[visit](const key_type& k, F f) const;
+ template size_t xref:#concurrent_flat_set_cvisit[cvisit](const key_type& k, F f) const;
+ template size_t xref:#concurrent_flat_set_cvisit[visit](const K& k, F f);
+ template size_t xref:#concurrent_flat_set_cvisit[visit](const K& k, F f) const;
+ template size_t xref:#concurrent_flat_set_cvisit[cvisit](const K& k, F f) const;
+
+ template
+ size_t xref:concurrent_flat_set_bulk_visit[visit](FwdIterator first, FwdIterator last, F f);
+ template
+ size_t xref:concurrent_flat_set_bulk_visit[visit](FwdIterator first, FwdIterator last, F f) const;
+ template
+ size_t xref:concurrent_flat_set_bulk_visit[cvisit](FwdIterator first, FwdIterator last, F f) const;
+
+ template size_t xref:#concurrent_flat_set_cvisit_all[visit_all](F f);
+ template size_t xref:#concurrent_flat_set_cvisit_all[visit_all](F f) const;
+ template size_t xref:#concurrent_flat_set_cvisit_all[cvisit_all](F f) const;
+ template
+ void xref:#concurrent_flat_set_parallel_cvisit_all[visit_all](ExecutionPolicy&& policy, F f);
+ template
+ void xref:#concurrent_flat_set_parallel_cvisit_all[visit_all](ExecutionPolicy&& policy, F f) const;
+ template
+ void xref:#concurrent_flat_set_parallel_cvisit_all[cvisit_all](ExecutionPolicy&& policy, F f) const;
+
+ template bool xref:#concurrent_flat_set_cvisit_while[visit_while](F f);
+ template bool xref:#concurrent_flat_set_cvisit_while[visit_while](F f) const;
+ template bool xref:#concurrent_flat_set_cvisit_while[cvisit_while](F f) const;
+ template
+ bool xref:#concurrent_flat_set_parallel_cvisit_while[visit_while](ExecutionPolicy&& policy, F f);
+ template
+ bool xref:#concurrent_flat_set_parallel_cvisit_while[visit_while](ExecutionPolicy&& policy, F f) const;
+ template
+ bool xref:#concurrent_flat_set_parallel_cvisit_while[cvisit_while](ExecutionPolicy&& policy, F f) const;
+
+ // capacity
+ ++[[nodiscard]]++ bool xref:#concurrent_flat_set_empty[empty]() const noexcept;
+ size_type xref:#concurrent_flat_set_size[size]() const noexcept;
+ size_type xref:#concurrent_flat_set_max_size[max_size]() const noexcept;
+
+ // modifiers
+ template bool xref:#concurrent_flat_set_emplace[emplace](Args&&... args);
+ bool xref:#concurrent_flat_set_copy_insert[insert](const value_type& obj);
+ bool xref:#concurrent_flat_set_move_insert[insert](value_type&& obj);
+ template bool xref:#concurrent_flat_set_transparent_insert[insert](K&& k);
+ template size_type xref:#concurrent_flat_set_insert_iterator_range[insert](InputIterator first, InputIterator last);
+ size_type xref:#concurrent_flat_set_insert_initializer_list[insert](std::initializer_list il);
+
+ template bool xref:#concurrent_flat_set_emplace_or_cvisit[emplace_or_visit](Args&&... args, F&& f);
+ template bool xref:#concurrent_flat_set_emplace_or_cvisit[emplace_or_cvisit](Args&&... args, F&& f);
+ template bool xref:#concurrent_flat_set_copy_insert_or_cvisit[insert_or_visit](const value_type& obj, F f);
+ template bool xref:#concurrent_flat_set_copy_insert_or_cvisit[insert_or_cvisit](const value_type& obj, F f);
+ template bool xref:#concurrent_flat_set_move_insert_or_cvisit[insert_or_visit](value_type&& obj, F f);
+ template bool xref:#concurrent_flat_set_move_insert_or_cvisit[insert_or_cvisit](value_type&& obj, F f);
+ template bool xref:#concurrent_flat_set_transparent_insert_or_cvisit[insert_or_visit](K&& k, F f);
+ template bool xref:#concurrent_flat_set_transparent_insert_or_cvisit[insert_or_cvisit](K&& k, F f);
+ template
+ size_type xref:#concurrent_flat_set_insert_iterator_range_or_visit[insert_or_visit](InputIterator first, InputIterator last, F f);
+ template
+ size_type xref:#concurrent_flat_set_insert_iterator_range_or_visit[insert_or_cvisit](InputIterator first, InputIterator last, F f);
+ template size_type xref:#concurrent_flat_set_insert_initializer_list_or_visit[insert_or_visit](std::initializer_list il, F f);
+ template size_type xref:#concurrent_flat_set_insert_initializer_list_or_visit[insert_or_cvisit](std::initializer_list il, F f);
+
+ template
+ bool xref:#concurrent_flat_set_emplace_and_cvisit[emplace_and_visit](Args&&... args, F1&& f1, F2&& f2);
+ template
+ bool xref:#concurrent_flat_set_emplace_and_cvisit[emplace_and_cvisit](Args&&... args, F1&& f1, F2&& f2);
+ template bool xref:#concurrent_flat_set_copy_insert_and_cvisit[insert_and_visit](const value_type& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_set_copy_insert_and_cvisit[insert_and_cvisit](const value_type& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_set_move_insert_and_cvisit[insert_and_visit](value_type&& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_set_move_insert_and_cvisit[insert_and_cvisit](value_type&& obj, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_set_transparent_insert_and_cvisit[insert_and_visit](K&& k, F1 f1, F2 f2);
+ template bool xref:#concurrent_flat_set_transparent_insert_and_cvisit[insert_and_cvisit](K&& k, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_set_insert_iterator_range_and_visit[insert_and_visit](InputIterator first, InputIterator last, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_set_insert_iterator_range_and_visit[insert_and_cvisit](InputIterator first, InputIterator last, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_set_insert_initializer_list_and_visit[insert_and_visit](std::initializer_list il, F1 f1, F2 f2);
+ template
+ size_type xref:#concurrent_flat_set_insert_initializer_list_and_visit[insert_and_cvisit](std::initializer_list il, F1 f1, F2 f2);
+
+ size_type xref:#concurrent_flat_set_erase[erase](const key_type& k);
+ template size_type xref:#concurrent_flat_set_erase[erase](const K& k);
+
+ template size_type xref:#concurrent_flat_set_erase_if_by_key[erase_if](const key_type& k, F f);
+ template size_type xref:#concurrent_flat_set_erase_if_by_key[erase_if](const K& k, F f);
+ template size_type xref:#concurrent_flat_set_erase_if[erase_if](F f);
+ template