From 552685784b6705ea0a3b8f4b0a806de0a8042cc7 Mon Sep 17 00:00:00 2001
From: Laurent Rineau <laurent.rineau@cgal.org>
Date: Wed, 8 Jan 2025 11:46:23 +0100
Subject: [PATCH] Add CGAL::unordered_flat_map implementation

...and `refactor Polyline_constraint_hierarchy_2` to use it.

`CGAL::unordered_flat_map` will be Boost `unordered_flat_map` if availlable, or the standard `std::unordered_map` otherwise.
---
 .../include/CGAL/unordered_flat_map.h         | 60 +++++++++++++++++++
 .../Polyline_constraint_hierarchy_2.h         | 15 +----
 2 files changed, 62 insertions(+), 13 deletions(-)
 create mode 100644 STL_Extension/include/CGAL/unordered_flat_map.h

diff --git a/STL_Extension/include/CGAL/unordered_flat_map.h b/STL_Extension/include/CGAL/unordered_flat_map.h
new file mode 100644
index 000000000000..45470c04d48b
--- /dev/null
+++ b/STL_Extension/include/CGAL/unordered_flat_map.h
@@ -0,0 +1,60 @@
+// Copyright (c) 2025 GeometryFactory Sarl (France).
+//
+// This file is part of CGAL (www.cgal.org).
+//
+// $URL$
+// $Id$
+// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
+//
+// Author(s)     : Laurent Rineau
+
+#ifndef CGAL_UNORDERED_FLAT_MAP_H
+#define CGAL_UNORDERED_FLAT_MAP_H
+
+#include <CGAL/config.h>
+
+#include <boost/version.hpp>
+#if BOOST_VERSION >= 108100 && !defined(CGAL_USE_BOOST_UNORDERED)
+#  define CGAL_USE_BOOST_UNORDERED 1
+#endif
+
+#if CGAL_USE_BARE_STD_MAP // to benchmark with the ordered std::map
+#  include <map>
+#elif CGAL_USE_BOOST_UNORDERED
+#  include <boost/unordered/unordered_flat_map.hpp>
+#else // Boost before 1.81.0, use the C++11 std::unordered_map
+#  include <unordered_map>
+#endif
+
+#if CGAL_USE_BARE_STD_MAP
+  #include <map>
+#endif
+
+#include <functional>
+
+namespace CGAL {
+
+template <
+  typename Key,
+  typename T,
+  typename Hash = std::hash<Key>,
+  typename KeyEqual = std::equal_to<Key>,
+  typename Allocator = std::allocator<std::pair<const Key, T>>
+  >
+#if CGAL_USE_BARE_STD_MAP
+
+  using unordered_flat_map = std::map<Key, T, std::less<Key>, Allocator>;
+
+#elif CGAL_USE_BOOST_UNORDERED
+
+  using unordered_flat_map = boost::unordered_flat_map<Key, T, Hash, KeyEqual, Allocator>;
+
+#else // use the C++11 std::unordered_map
+
+  using unordered_flat_map = std::unordered_map<Key, T, Hash, KeyEqual, Allocator>;
+
+#endif
+
+} // end namespace CGAL
+
+#endif // CGAL_UNORDERED_FLAT_MAP_H
diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h
index b96752e91fe5..6be1e8dd401b 100644
--- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h
+++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h
@@ -22,14 +22,7 @@
 #include <set>
 #include <list>
 
-#include <boost/version.hpp>
-#if BOOST_VERSION >= 108100
-#  include <boost/unordered/unordered_flat_map.hpp>
-#  define CGAL_USE_BOOST_UNORDERED 1
-#else // BOOST before 1.81.0
-#  include <unordered_map>
-#endif
-
+#include <CGAL/unordered_flat_map.h>
 #include <CGAL/Skiplist.h>
 #include <CGAL/assertions.h>
 
@@ -162,11 +155,7 @@ class Polyline_constraint_hierarchy_2
   typedef typename Context_list::iterator Context_iterator;
 
   typedef std::set<Constraint_id>           Constraint_set;
-#if CGAL_USE_BOOST_UNORDERED
-  typedef boost::unordered_flat_map<Edge, Context_list*, boost::hash<Edge>> Sc_to_c_map;
-#else
-  typedef std::unordered_map<Edge, Context_list*, boost::hash<Edge>> Sc_to_c_map;
-#endif
+  typedef CGAL::unordered_flat_map<Edge, Context_list*, boost::hash<Edge>> Sc_to_c_map;
   typedef typename Constraint_set::iterator C_iterator;
   typedef typename Sc_to_c_map::const_iterator    Sc_iterator;
   typedef Sc_iterator Subconstraint_iterator;