diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h
index 6b6d57339cd..e9053489a95 100644
--- a/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h
+++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h
@@ -1043,7 +1043,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a range over handles of the arrangement vertices .
+  returns a range over handles of the arrangement vertices.
   */
   Iterator_range<Prevent_deref<Vertex_iterator> >
   vertex_handles()
@@ -1068,7 +1068,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a const range (model of `ConstRange`) over handles of the arrangement vertices .
+  returns a const range (model of `ConstRange`) over handles of the arrangement vertices.
   */
   Iterator_range<Prevent_deref<Vertex_const_iterator> >
   vertex_handles() const
@@ -1098,7 +1098,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a range over handles of the arrangement halfedges .
+  returns a range over handles of the arrangement halfedges.
   */
   Iterator_range<Prevent_deref<Halfedge_iterator> >
   halfedge_handles()
@@ -1122,7 +1122,7 @@ class Arrangement_on_surface_2 {
                                     _Is_valid_halfedge(&m_topol_traits)));
   }
   /*!
-  returns a const range (model of `ConstRange`) over handles of the arrangement halfedges .
+  returns a const range (model of `ConstRange`) over handles of the arrangement halfedges.
   */
   Iterator_range<Prevent_deref<Halfedge_const_iterator> >
   halfedge_handles() const
@@ -1149,7 +1149,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a range over handles of the arrangement edges .
+  returns a range over handles of the arrangement edges.
   */
   Iterator_range<Prevent_deref<Edge_iterator> >
   edge_handles()
@@ -1172,7 +1172,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a const range (model of `ConstRange`) over handles of the arrangement edges .
+  returns a const range (model of `ConstRange`) over handles of the arrangement edges.
   */
   Iterator_range<Prevent_deref<Edge_const_iterator> >
   edge_handles() const
@@ -1199,7 +1199,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a range over handles of the arrangement faces .
+  returns a range over handles of the arrangement faces.
   */
   Iterator_range<Prevent_deref<Face_iterator> >
   face_handles()
@@ -1221,7 +1221,7 @@ class Arrangement_on_surface_2 {
   }
 
   /*!
-  returns a const range (model of `ConstRange`) over handles of the arrangement faces .
+  returns a const range (model of `ConstRange`) over handles of the arrangement faces.
   */
   Iterator_range<Prevent_deref<Face_const_iterator> >
   face_handles() const
diff --git a/Circulator/include/CGAL/circulator.h b/Circulator/include/CGAL/circulator.h
index 1c111779ef8..c622fb615ad 100644
--- a/Circulator/include/CGAL/circulator.h
+++ b/Circulator/include/CGAL/circulator.h
@@ -698,14 +698,18 @@ typedef Iterator_from_circulator< C, const_reference, const_pointer>
 };
 template <class Container>
 class Circulator_from_container {
+    static auto begin(Container* c) {
+        using std::begin;
+        return begin(*c);
+    }
+
+    static auto end(Container* c) {
+        using std::end;
+        return end(*c);
+    }
+
     typedef Circulator_from_container<Container>      Self;
-    typedef typename Container::iterator              container_iterator;
-    typedef typename Container::const_iterator        container_const_iterator;
-    typedef std::conditional_t<
-        std::is_const<Container>::value,
-        container_const_iterator,
-        container_iterator
-        >                                             iterator;
+    using iterator = decltype(begin(std::declval<Container*>()));
     typedef std::iterator_traits<iterator>            iterator_traits;
 public:
     typedef typename iterator_traits::value_type      value_type;
@@ -717,7 +721,7 @@ class Circulator_from_container {
         typename iterator_traits::iterator_category
         >::iterator_category                          iterator_category;
 
-    typedef typename Container::size_type size_type;
+    using size_type = decltype(std::size(std::declval<Container&>()));
 private:
     Container*     ctnr;
     iterator  i;
@@ -734,27 +738,27 @@ class Circulator_from_container {
     bool operator==( std::nullptr_t p) const {
         CGAL_USE(p);
         CGAL_assertion( p == nullptr);
-        return (ctnr == nullptr) || (ctnr->begin() == ctnr->end());
+        return (ctnr == nullptr) || (begin(ctnr) == end(ctnr));
     }
     bool operator!=( std::nullptr_t p) const { return !(*this == p); }
     bool operator==( const Self& c) const { return i == c.i; }
     bool operator!=( const Self& c) const { return !(*this == c); }
     reference  operator*() const {
         CGAL_assertion( ctnr != nullptr);
-        CGAL_assertion( i != ctnr->end());
+        CGAL_assertion( i != end(ctnr));
         return *i;
     }
     pointer  operator->() const {
         CGAL_assertion( ctnr != nullptr);
-        CGAL_assertion( i != ctnr->end());
+        CGAL_assertion( i != end(ctnr));
         return i.operator->();
     }
     Self& operator++() {
         CGAL_assertion( ctnr != nullptr);
-        CGAL_assertion( i != ctnr->end());
+        CGAL_assertion( i != end(ctnr));
         ++i;
-        if ( i == ctnr->end())
-            i = ctnr->begin();
+        if ( i == end(ctnr))
+            i = begin(ctnr);
         return *this;
     }
     Self operator++(int) {
@@ -764,9 +768,9 @@ class Circulator_from_container {
     }
     Self& operator--() {
         CGAL_assertion( ctnr != nullptr);
-        CGAL_assertion( i != ctnr->end());
-        if ( i == ctnr->begin())
-            i = ctnr->end();
+        CGAL_assertion( i != end(ctnr));
+        if ( i == begin(ctnr))
+            i = end(ctnr);
         --i;
         return *this;
     }
@@ -777,15 +781,15 @@ class Circulator_from_container {
     }
     Self& operator+=( difference_type n) {
         CGAL_assertion( ctnr != nullptr);
-        CGAL_assertion( i != ctnr->end());
-        typename Container::difference_type j    = i - ctnr->begin();
+        CGAL_assertion( i != end(ctnr));
+        typename Container::difference_type j    = i - begin(ctnr);
         typename Container::difference_type size = ctnr->size();
         CGAL_assertion( j    >= 0);
         CGAL_assertion( size >= 0);
         j = non_negative_mod( j + n, size);
         CGAL_assertion( j >= 0);
         CGAL_assertion( j < size);
-        i = ctnr->begin() + j;
+        i = begin(ctnr) + j;
         return *this;
     }
     Self operator+( difference_type n) const {
diff --git a/Hash_map/include/CGAL/Hash_map/internal/chained_map.h b/Hash_map/include/CGAL/Hash_map/internal/chained_map.h
index 729e2a58092..bea9b0993f0 100644
--- a/Hash_map/include/CGAL/Hash_map/internal/chained_map.h
+++ b/Hash_map/include/CGAL/Hash_map/internal/chained_map.h
@@ -19,6 +19,8 @@
 #include <CGAL/memory.h>
 #include <iostream>
 #include <limits>
+#include <type_traits>
+#include <utility>
 
 namespace CGAL {
 
@@ -85,6 +87,10 @@ class chained_map
    chained_map(std::size_t n = default_size, const T& d = T());
    chained_map(const chained_map<T, Allocator>& D);
    chained_map& operator=(const chained_map<T, Allocator>& D);
+   chained_map(chained_map<T, Allocator>&& D)
+     noexcept(std::is_nothrow_move_constructible_v<Allocator> && std::is_nothrow_move_constructible_v<T>);
+   chained_map& operator=(chained_map<T, Allocator>&& D)
+     noexcept(std::is_nothrow_move_assignable_v<Allocator> && std::is_nothrow_move_assignable_v<T>);
 
    void reserve(std::size_t n);
    void clear();
@@ -246,6 +252,18 @@ chained_map<T, Allocator>::chained_map(const chained_map<T, Allocator>& D)
     }
   }
 }
+template <typename T, typename Allocator>
+chained_map<T, Allocator>::chained_map(chained_map<T, Allocator>&& D)
+  noexcept(std::is_nothrow_move_constructible_v<Allocator> && std::is_nothrow_move_constructible_v<T>)
+  : table(std::exchange(D.table, nullptr))
+  , table_end(std::exchange(D.table_end, nullptr))
+  , free(std::exchange(D.free, nullptr))
+  , table_size(std::exchange(D.table_size, 0))
+  , table_size_1(std::exchange(D.table_size_1, 0))
+  , alloc(std::move(D.alloc))
+  , reserved_size(std::exchange(D.reserved_size, 0))
+  , def(std::move(D.def))
+{}
 
 template <typename T, typename Allocator>
 chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(const chained_map<T, Allocator>& D)
@@ -263,6 +281,24 @@ chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(const chained_ma
   return *this;
 }
 
+template <typename T, typename Allocator>
+chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(chained_map<T, Allocator>&& D)
+  noexcept(std::is_nothrow_move_assignable_v<Allocator> && std::is_nothrow_move_assignable_v<T>)
+{
+  clear();
+
+  table = std::exchange(D.table, nullptr);
+  table_end = std::exchange(D.table_end, nullptr);
+  free = std::exchange(D.free, nullptr);
+  table_size = std::exchange(D.table_size, 0);
+  table_size_1 = std::exchange(D.table_size_1, 0);
+  alloc = std::move(D.alloc);
+  reserved_size = std::exchange(D.reserved_size, 0);
+  def = std::move(D.def);
+
+  return *this;
+}
+
 template <typename T, typename Allocator>
 void chained_map<T, Allocator>::reserve(std::size_t n)
 {
diff --git a/Hash_map/test/Hash_map/Unique_hash_map_test.cpp b/Hash_map/test/Hash_map/Unique_hash_map_test.cpp
index 814fd7d94f3..bae896f360b 100644
--- a/Hash_map/test/Hash_map/Unique_hash_map_test.cpp
+++ b/Hash_map/test/Hash_map/Unique_hash_map_test.cpp
@@ -1,6 +1,7 @@
 #include <list>
 #include <CGAL/Unique_hash_map.h>
 #include <CGAL/test_macros.h>
+#include <type_traits>
 
 using namespace std;
 typedef list<int>::iterator Iterator;
@@ -24,6 +25,10 @@ int main() {
     H1[it1] = 2;
     CGAL_TEST(H1[it1]==2);
     CGAL_TEST(H2[it1]==-1);
+    static_assert(std::is_nothrow_move_constructible_v<decltype(H1)>);
+    auto H1_moved = std::move(H1);
+    CGAL_TEST(H1_moved[it1]==2);
+    CGAL_TEST(H1[it1]==H1.default_value());
     H1.clear();
     H2.clear(-2);
     H2[it1] = 2;
@@ -67,6 +72,7 @@ int main() {
     CGAL_TEST(get(H4_pmap, L.begin()) == 0);
 
     typedef CGAL::Unique_hash_map<int, int, Integer_hash_function>  Int_hmap;
+    static_assert(std::is_nothrow_move_constructible_v<Int_hmap>);
     typedef boost::associative_property_map<Int_hmap>               Int_pmap;
     Int_hmap H5(-1);
     Int_pmap H5_pmap(H5);
diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md
index b2dad48f364..541d4ad7463 100644
--- a/Installation/CHANGES.md
+++ b/Installation/CHANGES.md
@@ -1,8 +1,6 @@
-Release History
-===============
+# Release History
 
-[Release 6.0](https://github.com/CGAL/cgal/releases/tag/v6.0)
------------
+## [Release 6.0](https://github.com/CGAL/cgal/releases/tag/v6.0)
 
 Release date: June 2024
 
@@ -119,6 +117,9 @@ Release date: June 2024
 ### [Surface Mesh Parameterization](https://doc.cgal.org/6.0/Manual/packages.html#PkgSurfaceMeshParameterization)
 - **Breaking change**: LSCM_parameterizer_3 needs Eigen
 
+### [2D Triangulations](https://doc.cgal.org/6.0/Manual/packages.html#PkgTriangulation2)
+-   **Breaking change**: the concept [`TriangulationTraits_2`](https://doc.cgal.org/6.0/Triangulation_2/classTriangulationTraits__2.html) now requires an additional functor `Compare_xy_2`.
+
 ### [3D Triangulations](https://doc.cgal.org/6.0/Manual/packages.html#PkgTriangulation3)
 -   Added three functions `vertices()` to the class `Triangulation_3`.
     Each of them returns an array containing the vertices of the given triangulation simplex.
diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h
index c31b233091e..bd5dafbf017 100644
--- a/Installation/include/CGAL/config.h
+++ b/Installation/include/CGAL/config.h
@@ -293,7 +293,9 @@ using std::max;
 // Macros to detect features of clang. We define them for the other
 // compilers.
 // See https://clang.llvm.org/docs/LanguageExtensions.html
-// See also https://en.cppreference.com/w/cpp/experimental/feature_test
+//
+// Some of those macro have been standardized. See C++20 feature testing:
+//   https://en.cppreference.com/w/cpp/feature_test
 #ifndef __has_feature
   #define __has_feature(x) 0  // Compatibility with non-clang compilers.
 #endif
@@ -316,6 +318,10 @@ using std::max;
   #define __has_warning(x) 0  // Compatibility with non-clang compilers.
 #endif
 
+#if __has_include(<version>)
+#  include <version>
+#endif
+
 // Macro to specify a 'unused' attribute.
 #if __has_cpp_attribute(maybe_unused)
 #  define CGAL_UNUSED [[maybe_unused]]
@@ -470,6 +476,14 @@ namespace cpp11{
 }//namespace cpp11
 } //namespace CGAL
 
+#if __cpp_lib_concepts >= 201806L
+#  define CGAL_CPP20_REQUIRE_CLAUSE(x) requires x
+#  define CGAL_TYPE_CONSTRAINT(x) x
+#else
+#  define CGAL_CPP20_REQUIRE_CLAUSE(x)
+#  define CGAL_TYPE_CONSTRAINT(x) typename
+#endif
+
 // The fallthrough attribute
 // See for clang:
 //   https://clang.llvm.org/docs/AttributeReference.html#statement-attributes
@@ -487,6 +501,10 @@ namespace cpp11{
 #  define CGAL_FALLTHROUGH while(false){}
 #endif
 
+#if __cpp_lib_format >= 201907L || (__has_include(<format>) && (__cplusplus >= 202000L || _MSVC_LANG >= 202000L))
+#  define CGAL_CAN_USE_CXX20_FORMAT 1
+#endif
+
 #ifndef CGAL_NO_ASSERTIONS
 #  define CGAL_NO_ASSERTIONS_BOOL false
 #else
diff --git a/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h b/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h
index 07a13938bee..be7d5862fb3 100644
--- a/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h
+++ b/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h
@@ -291,6 +291,24 @@ class Voronoi_intersection_2_traits_3
   typedef typename Rep::Less_distance_to_point_3    Less_distance_to_point_2;
   typedef typename Rep::Compute_squared_distance_3  Compute_squared_distance_2;
 
+  struct Compare_xy_2 {
+    Compare_x_2 cx_2;
+    Compare_y_2 cy_2;
+
+    Compare_xy_2(const Compare_x_2& cx_2, const Compare_y_2& cy_2)
+      : cx_2(cx_2), cy_2(cy_2)
+    {}
+
+    Comparison_result operator()(const Point_2& p, const Point_2& q) const
+    {
+       Comparison_result res = cx_2(p, q);
+       if (res == EQUAL) {
+         return cy_2(p, q);
+       }
+       return res;
+    }
+  };
+
   //instantiations and creation of functors:
   //for the triangulation:
   Orientation_2
@@ -312,6 +330,10 @@ class Voronoi_intersection_2_traits_3
   compare_y_2_object() const
   { return Compare_y_2(normal); }
 
+  Compare_xy_2
+  compare_xy_2_object() const
+  { return Compare_xy_2(compare_x_2_object(), compare_y_2_object()); }
+
   Less_x_2
   less_x_2_object() const
   { return compare_to_less(compare_x_2_object()); }
diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h
index 71e56de4785..d8ae9f4bbf4 100644
--- a/Kernel_23/include/CGAL/Kernel/function_objects.h
+++ b/Kernel_23/include/CGAL/Kernel/function_objects.h
@@ -205,6 +205,44 @@ namespace CommonKernelFunctors {
   public:
     typedef typename K::Comparison_result  result_type;
 
+    result_type
+    operator()(const Point_3& a1, const Point_3& b1, const Point_3& c1,
+               const Point_3& a2, const Point_3& b2, const Point_3& c2) const
+    {
+      using FT = typename K::FT;
+      const Vector_3 ba1 = a1 - b1;
+      const Vector_3 bc1 = c1 - b1;
+      const Vector_3 ba2 = a2 - b2;
+      const Vector_3 bc2 = c2 - b2;
+      const FT sc_prod_1 = ba1 * bc1;
+      const FT sc_prod_2 = ba2 * bc2;
+      // Reminder: cos(angle) = scalar_product(ba, bc) / (length(ba)*length(bc))
+      // cosine is decreasing on 0, pi
+      // thus angle1 < angle2 is equivalent to cos(angle1) > cos(angle2)
+      if(sc_prod_1 >= 0) {
+        if(sc_prod_2 >= 0) {
+          // the two cosine are >= 0, we can compare the squares
+          // (square(x) is increasing when x>=0
+          return CGAL::compare(CGAL::square(sc_prod_2)*
+                               ba1.squared_length()*bc1.squared_length(),
+                               CGAL::square(sc_prod_1)*
+                               ba2.squared_length()*bc2.squared_length());
+        } else {
+          return SMALLER;
+        }
+      } else {
+        if(sc_prod_2 < 0) {
+          // the two cosine are < 0, square(x) is decreasing when x<0
+          return CGAL::compare(CGAL::square(sc_prod_1)*
+                               ba2.squared_length()*bc2.squared_length(),
+                               CGAL::square(sc_prod_2)*
+                               ba1.squared_length()*bc1.squared_length());
+        } else {
+          return LARGER;
+        }
+      }
+    }
+
     result_type
     operator()(const Point_3& a, const Point_3& b, const Point_3& c,
                const FT& cosine) const
diff --git a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h
index 1cc09421944..bc691bf27d7 100644
--- a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h
+++ b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h
@@ -971,6 +971,7 @@ class Projection_traits_3
   typedef typename Rp::Construct_triangle_3                   Construct_triangle_2;
   typedef typename Rp::Construct_line_3                       Construct_line_2;
 
+  typedef typename Rp::Compare_xyz_3                          Compare_xy_2;
 
   struct Less_xy_2 {
     typedef typename R::Boolean result_type;
@@ -1065,6 +1066,10 @@ class Projection_traits_3
   less_x_2_object() const
     { return Less_x_2();}
 
+  Compare_xy_2
+  compare_xy_2_object() const
+    { return Compare_xy_2();}
+
   Less_xy_2
   less_xy_2_object() const
     { return Less_xy_2();}
diff --git a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h
index 089fe5ba6cb..e179fecc677 100644
--- a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h
+++ b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h
@@ -426,6 +426,7 @@ class Projection_traits_base_3
   typedef typename K::Line_3      Line_2;
 
   typedef typename K::Angle_3                                Angle_2;
+  typedef typename K::Compare_xyz_3                          Compare_xy_2;
 
   typedef TriangulationProjectionTraitsCartesianFunctors::
     Compare_along_axis<Self>                                 Compare_x_2;
@@ -524,6 +525,9 @@ class Projection_traits_base_3
   Angle_2  angle_2_object() const
     {return Angle_2();}
 
+  Compare_xy_2  compare_xy_2_object() const
+    {return Compare_xy_2();}
+
   Construct_point_2  construct_point_2_object() const
     {return Construct_point_2();}
 
diff --git a/Mesh_3/test/Mesh_3/test_meshing_utilities.h b/Mesh_3/test/Mesh_3/test_meshing_utilities.h
index 5b5fbc61316..72e2a245c31 100644
--- a/Mesh_3/test/Mesh_3/test_meshing_utilities.h
+++ b/Mesh_3/test/Mesh_3/test_meshing_utilities.h
@@ -71,6 +71,8 @@ void verify_time_stamps(const C3t3& c3t3, CGAL::Sequential_tag) {
       assert(prev->time_stamp() < cit->time_stamp());
     }
   }
+  assert(tds.vertices().check_timestamps_are_valid());
+  assert(tds.cells().check_timestamps_are_valid());
 }
 
 // Do not verify time stamps in parallel mode
diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h
index 3d6d588b142..87091d84300 100644
--- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h
+++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h
@@ -48,6 +48,25 @@ template <class Base_> struct Kernel_2_interface : public Base_ {
         typedef Help_2p_i<Less_point_cartesian_coordinate_tag,1> Less_y_2;
         typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,0> Compare_x_2;
         typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,1> Compare_y_2;
+
+        struct Compare_xy_2 {
+                Compare_x_2 cx_2;
+                Compare_y_2 cy_2;
+
+                Compare_xy_2(const Compare_x_2 & cx_2, const Compare_y_2 & cy_2)
+                  : cx_2(cx_2), cy_2(cy_2)
+                {}
+
+                typename Compare_x_2::result_type operator()(const Point_2 & p, const Point_2 & q)
+                {
+                        auto res = cx_2(p, q);
+                        if (res == EQUAL) {
+                                return cy_2(p, q);
+                        }
+                        return res;
+                }
+        };
+
         struct Compare_distance_2 {
                 typedef typename Get_functor<Base, Compare_distance_tag>::type CD;
                 typedef typename CD::result_type result_type;
@@ -88,6 +107,9 @@ template <class Base_> struct Kernel_2_interface : public Base_ {
         Less_y_2 less_y_2_object()const{ return Less_y_2(*this); }
         Compare_x_2 compare_x_2_object()const{ return Compare_x_2(*this); }
         Compare_y_2 compare_y_2_object()const{ return Compare_y_2(*this); }
+
+        Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(compare_x_2_object(), compare_y_2_object()); }
+
         Compare_distance_2 compare_distance_2_object()const{ return Compare_distance_2(*this); }
         Orientation_2 orientation_2_object()const{ return Orientation_2(*this); }
         Side_of_oriented_circle_2 side_of_oriented_circle_2_object()const{ return Side_of_oriented_circle_2(*this); }
diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt
index 4bc63fcf8b3..67743dbd907 100644
--- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt
+++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt
@@ -9,6 +9,7 @@ find_package(CGAL REQUIRED)
 
 create_single_source_cgal_program("sample_example.cpp" )
 create_single_source_cgal_program("extrude.cpp" )
+create_single_source_cgal_program( "list_non_pure_triangle_meshes.cpp" )
 create_single_source_cgal_program("polyhedral_envelope.cpp" )
 create_single_source_cgal_program("polyhedral_envelope_of_triangle_soup.cpp" )
 create_single_source_cgal_program("polyhedral_envelope_mesh_containment.cpp" )
diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/list_non_pure_triangle_meshes.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/list_non_pure_triangle_meshes.cpp
new file mode 100644
index 00000000000..b885602f54d
--- /dev/null
+++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/list_non_pure_triangle_meshes.cpp
@@ -0,0 +1,29 @@
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h>
+#include <CGAL/Surface_mesh.h>
+
+#include <CGAL/boost/graph/helpers.h>
+
+#include <iostream>
+#include <string>
+
+typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
+typedef Kernel::Point_3 Point;
+typedef CGAL::Surface_mesh<Point> Surface_mesh;
+
+namespace PMP = CGAL::Polygon_mesh_processing;
+
+int main(int argc, char* argv[])
+{
+  for(int i = 1; i < argc; ++i) {
+    Surface_mesh mesh;
+    if(!PMP::IO::read_polygon_mesh(argv[i], mesh)) {
+      std::cerr << "Invalid input: " << argv[i] << '\n';
+    }
+    if(!is_triangle_mesh(mesh)) {
+      std::cout << argv[i] << std::endl;
+    }
+  }
+
+  return 0;
+}
diff --git a/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h
index c58110c9b32..db0cc2fa28d 100644
--- a/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h
+++ b/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h
@@ -444,8 +444,8 @@ class Mesh_complex_3_in_triangulation_3
    */
   void remove_from_complex(const Vertex_handle& v)
   {
-    corners_.erase(v);
     v->set_dimension(-1);
+    corners_.erase(v);
   }
 
   /** sets the index of vertex \p vertex to \p index
@@ -983,7 +983,7 @@ class Mesh_complex_3_in_triangulation_3
     pointer operator->() const { return *(this->base()); }
     reference operator*() const { return **(this->base()); }
 
-    operator Vertex_handle() { return Vertex_handle(*(this->base())); }
+    operator const Vertex_handle&() const { return *(this->base()); }
   };
 
 public:
@@ -1048,13 +1048,13 @@ class Mesh_complex_3_in_triangulation_3
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
 
-    operator Cell_handle() const { return Cell_handle(this->base()); }
+    operator const Cell_handle&() const { return this->base(); }
   }; // end class Cells_in_complex_iterator
 
-  typedef Iterator_range<Prevent_deref<Vertices_in_complex_iterator> > Vertices_in_complex;
-  typedef Iterator_range<Edges_in_complex_iterator>                    Edges_in_complex;
-  typedef Iterator_range<Facets_in_complex_iterator>                   Facets_in_complex;
-  typedef Iterator_range<Prevent_deref<Cells_in_complex_iterator> >    Cells_in_complex;
+  typedef Iterator_range<Prevent_deref<Vertices_in_complex_iterator, const Vertex_handle&>> Vertices_in_complex;
+  typedef Iterator_range<Edges_in_complex_iterator> Edges_in_complex;
+  typedef Iterator_range<Facets_in_complex_iterator> Facets_in_complex;
+  typedef Iterator_range<Prevent_deref<Cells_in_complex_iterator, const Cell_handle&>> Cells_in_complex;
 
 #endif
 
@@ -1162,8 +1162,7 @@ class Mesh_complex_3_in_triangulation_3
   */
   Vertices_in_complex vertices_in_complex() const
   {
-    return make_prevent_deref_range(vertices_in_complex_begin(),
-                                    vertices_in_complex_end());
+      return { vertices_in_complex_begin(), vertices_in_complex_end() };
   }
   /*!
     returns a range of iterators over the edges of the 1D complex,
@@ -1193,8 +1192,7 @@ class Mesh_complex_3_in_triangulation_3
   */
   Cells_in_complex cells_in_complex() const
   {
-    return make_prevent_deref_range(cells_in_complex_begin(),
-                                    cells_in_complex_end());
+    return { cells_in_complex_begin(), cells_in_complex_end() };
   }
 ///  @}
 
diff --git a/SMDS_3/include/CGAL/SMDS_3/io_signature.h b/SMDS_3/include/CGAL/SMDS_3/io_signature.h
index 1a5f6e54aa3..bae31c072c7 100644
--- a/SMDS_3/include/CGAL/SMDS_3/io_signature.h
+++ b/SMDS_3/include/CGAL/SMDS_3/io_signature.h
@@ -27,6 +27,7 @@
 #include <CGAL/Regular_triangulation_3.h>
 #include <CGAL/Regular_triangulation_cell_base_3.h>
 #include <CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h>
+#include <CGAL/type_traits.h>
 
 #ifdef CGAL_PERIODIC_3_MESH_3_CONFIG_H
 #include <CGAL/Periodic_3_triangulation_3.h>
@@ -36,21 +37,17 @@
 #include <variant>
 #include <boost/tuple/tuple.hpp>
 #include <utility>
+#include <type_traits>
 
 namespace CGAL {
 
 // SFINAE test
-template <typename T, typename U>
-class has_io_signature
-{
-private:
-  template <U> struct helper;
-  template <typename V> static char check(helper<&V::io_signature> *);
-  template <typename V> static char (&check(...))[2];
+template <typename T, class = void>
+struct has_io_signature : public std::false_type {};
 
-public:
-  enum { value = (sizeof(check<T>(0)) == sizeof(char)) };
-};
+template <typename T>
+struct has_io_signature<T, std::void_t<decltype(T::io_signature())>>
+: public std::true_type {};
 
 template <class T, bool has_io_signature>
 struct Get_io_signature_aux
@@ -76,10 +73,7 @@ template <class T>
 struct Get_io_signature
   : public Get_io_signature_aux<
   T,
-  (has_io_signature<T, std::string (T::*)() >::value ||
-   has_io_signature<T, std::string (T::*)() const >::value ||
-   has_io_signature<T, std::string (*)() >::value )  // signature for
-                                                     // static mem func
+  has_io_signature<T>::value
   >
 {
 };
@@ -366,6 +360,18 @@ Get_io_signature<Regular_triangulation_cell_base_with_weighted_circumcenter_3<Gt
 };
 #endif
 
+#ifdef CGAL_BASE_WITH_TIME_STAMP_H
+template <class Base>
+struct
+Get_io_signature<Base_with_time_stamp<Base> >
+{
+  std::string operator()() {
+    return Get_io_signature<Base>()();
+  }
+};
+#endif
+
+
 } // end namespace CGAL
 
 
diff --git a/SMDS_3/test/SMDS_3/test_c3t3.cpp b/SMDS_3/test/SMDS_3/test_c3t3.cpp
index 78835c78fda..9fe7b744aae 100644
--- a/SMDS_3/test/SMDS_3/test_c3t3.cpp
+++ b/SMDS_3/test/SMDS_3/test_c3t3.cpp
@@ -49,6 +49,9 @@ struct Tester
   typedef typename C3t3::Facets_in_complex_iterator Facet_iterator;
   typedef typename C3t3::Vertex_handle Vertex_handle;
 
+  typedef typename C3t3::Vertices_in_complex Vertices_in_complex;
+  typedef typename C3t3::Cells_in_complex Cells_in_complex;
+
   typedef typename C3t3::Subdomain_index Subdomain_index;
   typedef typename C3t3::Surface_patch_index Surface_patch_index;
   typedef typename C3t3::Index Index;
@@ -120,6 +123,15 @@ struct Tester
     assert(c3t3.is_in_complex(ch));
     assert(c3t3.subdomain_index(ch) == subdomain_index);
 
+    // Test iterator range
+    {
+      Cell_handle ch = *c3t3.cells_in_complex().begin();
+      for (auto c : c3t3.cells_in_complex()) {
+        assert(c == ch);
+        break;
+      }
+    }
+
     //-------------------------------------------------------
     // Test move construction
     //-------------------------------------------------------
diff --git a/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp b/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp
index 737bfcacb33..4373da1fdc0 100644
--- a/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp
+++ b/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp
@@ -218,6 +218,18 @@ struct Tester
            || ( v == vp4 && tr.point(vit) == p4 ) );
 
     assert ( tv1.in_dimension() == tv2.in_dimension() );
+
+
+    // Test iterator range
+    {
+      Vertex_handle vh =  *c3t3.vertices_in_complex().begin();
+      for (auto v : c3t3.vertices_in_complex()) {
+        assert(v == vh);
+        break;
+      }
+    }
+
+
     //-------------------------------------------------------
     // Check adjacencies
     //-------------------------------------------------------
@@ -335,8 +347,13 @@ struct Tester
     //-------------------------------------------------------
     std::cout << "Test vertex iterators\n";
     const Vertex_handle& vertex_to_modify = c3t3.vertices_in_complex_begin();
+    Vertex_handle vertex_to_modify_copy = vertex_to_modify;
+
     c3t3.remove_from_complex(vertex_to_modify);
-    c3t3.add_to_complex(vertex_to_modify,corner_index_bis);
+    // now `vertex_to_modify` is a dangling ref to a `Vertex_handle`
+
+    // use a copy of it: `vertex_to_modify_copy`
+    c3t3.add_to_complex(vertex_to_modify_copy,corner_index_bis);
 
     typename C3t3::Vertices_in_complex_iterator corner_vit =
       c3t3.vertices_in_complex_begin(corner_index);
diff --git a/STL_Extension/include/CGAL/Base_with_time_stamp.h b/STL_Extension/include/CGAL/Base_with_time_stamp.h
index cbed66de81f..962eec8a1e1 100644
--- a/STL_Extension/include/CGAL/Base_with_time_stamp.h
+++ b/STL_Extension/include/CGAL/Base_with_time_stamp.h
@@ -18,9 +18,11 @@ namespace CGAL {
 
 template <typename Base>
 class Base_with_time_stamp : public Base {
-  std::size_t time_stamp_ = -1;
+  std::size_t time_stamp_ = std::size_t(-2);
 public:
-  typedef CGAL::Tag_true Has_timestamp;
+  using Base::Base;
+
+  using Has_timestamp = CGAL::Tag_true;
 
   std::size_t time_stamp() const {
     return time_stamp_;
diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h
index 81ff5cf1bce..073300c8a82 100644
--- a/STL_Extension/include/CGAL/Compact_container.h
+++ b/STL_Extension/include/CGAL/Compact_container.h
@@ -27,6 +27,7 @@
 #include <functional>
 #include <atomic>
 
+#include <CGAL/use.h>
 #include <CGAL/memory.h>
 #include <CGAL/iterator.h>
 #include <CGAL/CC_safe_handle.h>
@@ -271,7 +272,7 @@ class Compact_container
   {
     init();
     block_size = c.block_size;
-    time_stamp = c.time_stamp.load();
+    time_stamp = 0;
     std::copy(c.begin(), c.end(), CGAL::inserter(*this));
   }
 
@@ -302,6 +303,20 @@ class Compact_container
     clear();
   }
 
+  bool check_timestamps_are_valid() const {
+    if constexpr (Time_stamper::has_timestamp) {
+      for(size_type i = 0, end = capacity(); i < end; ++i) {
+        if(!is_used(i)) {
+          continue;
+        }
+        if(Time_stamper::time_stamp(&operator[](i)) != i) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
   bool is_used(const_iterator ptr) const
   {
     return (type(&*ptr)==USED);
@@ -382,10 +397,18 @@ class Compact_container
 
     pointer ret = free_list;
     free_list = clean_pointee(ret);
+    std::size_t ts;
+    CGAL_USE(ts);
+    if constexpr (Time_stamper::has_timestamp) {
+      ts = ret->time_stamp();
+    }
     new (ret) value_type(args...);
+    if constexpr (Time_stamper::has_timestamp) {
+      ret->set_time_stamp(ts);
+    }
+    Time_stamper::set_time_stamp(ret, time_stamp);
     CGAL_assertion(type(ret) == USED);
     ++size_;
-    Time_stamper::set_time_stamp(ret, time_stamp);
     return iterator(ret, 0);
   }
 
@@ -396,10 +419,18 @@ class Compact_container
 
     pointer ret = free_list;
     free_list = clean_pointee(ret);
+    std::size_t ts;
+    CGAL_USE(ts);
+    if constexpr (Time_stamper::has_timestamp) {
+      ts = ret->time_stamp();
+    }
     std::allocator_traits<allocator_type>::construct(alloc, ret, t);
+    if constexpr (Time_stamper::has_timestamp) {
+      ret->set_time_stamp(ts);
+    }
+    Time_stamper::set_time_stamp(ret, time_stamp);
     CGAL_assertion(type(ret) == USED);
     ++size_;
-    Time_stamper::set_time_stamp(ret, time_stamp);
     return iterator(ret, 0);
   }
 
@@ -424,7 +455,15 @@ class Compact_container
 
     CGAL_precondition(type(&*x) == USED);
     EraseCounterStrategy::increment_erase_counter(*x);
+    std::size_t ts;
+    CGAL_USE(ts);
+    if constexpr (Time_stamper::has_timestamp) {
+      ts = x->time_stamp();
+    }
     std::allocator_traits<allocator_type>::destroy(alloc, &*x);
+    if constexpr (Time_stamper::has_timestamp) {
+      x->set_time_stamp(ts);
+    }
 
     put_on_free_list(&*x);
     --size_;
@@ -1166,6 +1205,61 @@ class Output_rep<CGAL::internal::CC_iterator<DSC, Const> > {
   }
 };
 
+struct With_offset_tag {
+  int offset = 0;
+};
+
+struct With_point_tag : public With_offset_tag {
+};
+
+struct With_point_and_info_tag : public With_point_tag {};
+
+template <class DSC, bool Const>
+struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_offset_tag>
+  : public Output_rep<CGAL::internal::CC_iterator<DSC, Const>>
+{
+  int offset = 0;
+
+  using CC_iterator = CGAL::internal::CC_iterator<DSC, Const>;
+  using Compact_container = typename CC_iterator::CC;
+  using Time_stamper = typename Compact_container::Time_stamper;
+  using Base = Output_rep<CC_iterator>;
+  using Base::Base;
+
+  Output_rep(const CC_iterator it, With_offset_tag tag = {})
+    : Base(it), offset(tag.offset) {}
+
+  std::ostream& operator()(std::ostream& out) const {
+    out << Time_stamper::display_id(this->it.operator->(), offset);
+    return out;
+  }
+};
+
+template <class DSC, bool Const>
+struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_point_tag>
+  : public Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_offset_tag>
+{
+  using CC_iterator = CGAL::internal::CC_iterator<DSC, Const>;
+  using Base = Output_rep<CC_iterator, With_offset_tag>;
+  using Time_stamper = typename Base::Time_stamper;
+
+  using Base::Base;
+
+  Output_rep(const CC_iterator it, With_point_tag tag = {})
+    : Base(it, tag) {}
+
+  std::ostream& operator()(std::ostream& out) const {
+    this->Base::operator()(out);
+    if(this->it.operator->() != nullptr) {
+      if(Time_stamper::time_stamp(this->it.operator->()) == 0)
+        return out << "= infinite_vertex()";
+      return out << "= " << this->it->point();
+    }
+    else
+      return out;
+  }
+};
+
 } //namespace CGAL
 
 namespace std {
@@ -1183,7 +1277,6 @@ namespace std {
   };
 #endif // CGAL_CFG_NO_STD_HASH
 
-
 } // namespace std
 
 #include <CGAL/enable_warnings.h>
diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h
index f48f5307ef0..295717b8041 100644
--- a/STL_Extension/include/CGAL/Time_stamper.h
+++ b/STL_Extension/include/CGAL/Time_stamper.h
@@ -28,12 +28,15 @@ constexpr size_t rounded_down_log2(size_t n)
 template <typename T>
 struct Time_stamper
 {
+  static constexpr bool has_timestamp = true;
+
   static void initialize_time_stamp(T* pt) {
     pt->set_time_stamp(std::size_t(-1));
   }
 
   template <typename time_stamp_t>
   static void set_time_stamp(T* pt, time_stamp_t& time_stamp_) {
+    CGAL_assertion(pt->time_stamp() != std::size_t(-2));
     if(pt->time_stamp() == std::size_t(-1)) {
       const std::size_t new_ts = time_stamp_++;
       pt->set_time_stamp(new_ts);
@@ -61,18 +64,23 @@ struct Time_stamper
 
   static std::size_t time_stamp(const T* pt)
   {
+    CGAL_assertion(pt == nullptr || pt->time_stamp() != std::size_t(-2));
     if(pt == nullptr){
       return std::size_t(-1);
     }
     return pt->time_stamp();
   }
 
-  static auto display_id(const T* pt)
+  static auto display_id(const T* pt, int offset = 0)
   {
-    return std::string("#") + std::to_string(pt->time_stamp());
+    if(pt == nullptr)
+      return std::string("nullptr");
+    else
+      return std::string("#") + std::to_string(pt->time_stamp() + offset);
   }
 
   static std::size_t hash_value(const T* p) {
+    CGAL_assertion(p == nullptr || p->time_stamp() != std::size_t(-2));
     if(nullptr == p)
       return std::size_t(-1);
     else
@@ -92,6 +100,7 @@ struct Time_stamper
 template <typename T>
 struct No_time_stamp
 {
+  static constexpr bool has_timestamp = false;
 public:
   template <typename time_stamp_t>
   static void set_time_stamp(T*, time_stamp_t&)  {}
@@ -107,7 +116,7 @@ struct No_time_stamp
     return 0;
   }
 
-  static auto display_id(const T* pt)
+  static auto display_id(const T* pt, int)
   {
     return static_cast<const void*>(pt);
   }
diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h
index 326557344a6..0e72a1ed44e 100644
--- a/STL_Extension/include/CGAL/iterator.h
+++ b/STL_Extension/include/CGAL/iterator.h
@@ -25,6 +25,7 @@
 #include <CGAL/circulator.h>
 #include <CGAL/Iterator_range.h>
 #include <CGAL/tuple.h>
+#include <CGAL/type_traits.h>
 #include <CGAL/use.h>
 
 #include <variant>
@@ -37,28 +38,34 @@
 
 namespace CGAL {
 
-template<typename I>
+template<typename I, typename Reference_type = const I&>
 class Prevent_deref
   : public boost::iterator_adaptor<
-  Prevent_deref<I>
+    Prevent_deref<I, Reference_type>
   , I // base
-  , I // value
+  , CGAL::cpp20::remove_cvref_t<Reference_type> // value
+  , boost::use_default // category
+  , Reference_type // ref
   >
 {
 public:
-  typedef boost::iterator_adaptor<
-  Prevent_deref<I>
+  using Value_type = CGAL::cpp20::remove_cvref_t<Reference_type>;
+  using Base = boost::iterator_adaptor<
+    Prevent_deref<I, Reference_type>
   , I // base
-  , I // value
-  > Base;
-  typedef typename Base::reference reference;
+  , Value_type // value
+  , boost::use_default // category
+  , Reference_type // ref
+  >;
   typedef typename std::pair<I, I> range;
 
-  Prevent_deref() : Base() {}
+  Prevent_deref() = default;
   Prevent_deref(const I& i) : Base(i) {}
 private:
   friend class boost::iterator_core_access;
-  reference dereference() const { return const_cast<std::remove_reference_t<reference>&>(this->base_reference()); }
+  Reference_type dereference() const {
+    return this->base_reference();
+  }
 };
 
 template<typename I>
@@ -608,7 +615,7 @@ struct Filter_iterator {
   reference operator*() const { return *c_;  }
   pointer operator->() const  { return &*c_; }
   const Predicate& predicate() const { return p_; }
-  Iterator base() const { return c_; }
+  const Iterator& base() const { return c_; }
 
   Iterator end() const { return e_; }
   bool is_end() const { return (c_ == e_); }
diff --git a/STL_Extension/include/CGAL/utility.h b/STL_Extension/include/CGAL/utility.h
index 277476c6079..88f63fb115b 100644
--- a/STL_Extension/include/CGAL/utility.h
+++ b/STL_Extension/include/CGAL/utility.h
@@ -295,22 +295,8 @@ struct Default_using_type
   };
 };
 
-template <class T_ = Default_using_type>
-struct less_cpp14
-{
-  template <class T1, class T2>
-  bool operator() (T1&& t1, T2&& t2) const
-  {
-    typedef typename Default_using_type::Get<
-      T_,
-      typename std::common_type<typename std::decay<T1>::type,
-                                typename std::decay<T2>::type> >::type T;
-    return std::less<T>()(t1,t2);
-  }
-};
-
 template <class T = Default_using_type,
-          class Compare = less_cpp14<T>,
+          class Compare = std::less<>,
           class T1, class T2,
           class A = typename Default_using_type::Get<T,
             typename std::common_type<
@@ -323,6 +309,40 @@ inline P make_sorted_pair(T1&& t1, T2&& t2, Compare comp = Compare())
                       : P(std::forward<T2>(t2), std::forward<T1>(t1));
 }
 
+template <class Pair>
+auto make_sorted_pair(Pair&& pair) {
+  auto&& [a, b] = std::forward<Pair>(pair);
+  return make_sorted_pair(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b));
+}
+
+template <class F>
+class [[nodiscard]] Scope_exit {
+  CGAL_NO_UNIQUE_ADDRESS F exit_function;
+
+public:
+  template <typename G>
+  explicit Scope_exit(G&& g, std::enable_if_t<!std::is_same_v<std::decay_t<G>, Scope_exit>>* = nullptr)
+      : exit_function(std::forward<G>(g))
+  {
+  }
+
+  Scope_exit(const Scope_exit&) = delete;
+  Scope_exit& operator=(const Scope_exit&) = delete;
+  Scope_exit(Scope_exit&&) = delete;
+  Scope_exit& operator=(Scope_exit&&) = delete;
+
+  ~Scope_exit() {
+    exit_function();
+  }
+};
+
+template<typename F> Scope_exit(F) -> Scope_exit<F>;
+
+template <typename F>
+Scope_exit<F> make_scope_exit(F&& f) {
+  return Scope_exit<F>(std::forward<F>(f));
+}
+
 } //namespace CGAL
 
 namespace std {
diff --git a/STL_Extension/test/STL_Extension/CMakeLists.txt b/STL_Extension/test/STL_Extension/CMakeLists.txt
index 3b54df0088d..4207a5aef8e 100644
--- a/STL_Extension/test/STL_Extension/CMakeLists.txt
+++ b/STL_Extension/test/STL_Extension/CMakeLists.txt
@@ -12,6 +12,7 @@ if(NOT TARGET CGAL::TBB_support)
   message(STATUS "NOTICE: Tests are not using TBB.")
 endif()
 
+create_single_source_cgal_program("issue_7400.cpp")
 create_single_source_cgal_program("test_Boolean_tag.cpp")
 create_single_source_cgal_program("test_Cache.cpp")
 create_single_source_cgal_program("test_Compact_container.cpp")
diff --git a/STL_Extension/test/STL_Extension/issue_7400.cpp b/STL_Extension/test/STL_Extension/issue_7400.cpp
new file mode 100644
index 00000000000..d7787116610
--- /dev/null
+++ b/STL_Extension/test/STL_Extension/issue_7400.cpp
@@ -0,0 +1,54 @@
+#include <type_traits>
+#include <iterator>
+#include <CGAL/type_traits.h>
+
+// Add C++20 utilities to C++14
+template <class Iterator>
+using iter_value_t = std::remove_reference_t<decltype(*std::declval<Iterator>())>;
+
+template<class Range>
+using range_value_t = iter_value_t<CGAL::cpp20::remove_cvref_t<decltype(std::begin(std::declval<Range>()))>>;
+
+template< class T, class U >
+constexpr bool is_same_v = std::is_same<T, U>::value;
+
+template< class T, class U >
+constexpr bool is_convertible_v = std::is_convertible<T, U>::value;
+
+
+#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
+#include <CGAL/Triangulation_3.h>
+
+using Triangulation = CGAL::Triangulation_3<CGAL::Exact_predicates_inexact_constructions_kernel>;
+
+using Vertex_handle =  Triangulation::Vertex_handle;
+
+Triangulation t;
+
+// Tds::vertex_handles() -> Vertex_handle
+static_assert(is_same_v<range_value_t<decltype(t.tds().vertex_handles())>, const Vertex_handle>);
+
+// Triangulation::all_vertex_handles() -> Vertex_handle
+static_assert(is_same_v<range_value_t<decltype(t.all_vertex_handles())>, const Vertex_handle>);
+
+// Triangulation::finite_vertex_handles() -> convertible to Vertex_handle
+static_assert(is_convertible_v<decltype(*std::begin(t.finite_vertex_handles())), Vertex_handle>);
+
+// But is it equal to Vertex_handle
+static_assert(is_same_v<range_value_t<decltype(t.finite_vertex_handles())>, const Vertex_handle>);
+
+int main()
+{
+  Vertex_handle v_inf = t.infinite_vertex();
+  for(auto v: t.finite_vertex_handles()) {
+    Vertex_handle v2 = v;
+    CGAL_USE(v2);
+    if(v == v_inf) return 1;
+  }
+  for (auto v : t.all_vertex_handles()) {
+      Vertex_handle v2 = v;
+      CGAL_USE(v2);
+      if (v == v_inf) std::cout << "found inf" << std::endl;
+  }
+  return 0;
+}
diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp
index 60aa43db0e2..bf6b0d83948 100644
--- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp
+++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp
@@ -305,10 +305,10 @@ int main()
   typedef Node_1<CGAL::Tag_false> T2;
   typedef CGAL::Compact_container<T2> C2; // without timestamps
 
-  typedef CGAL::Compact_container<T2,
+  typedef CGAL::Compact_container<T1,
                                   CGAL::Default,
                                   CGAL::Default,
-                                  CGAL::Time_stamper<T2> > C4;
+                                  CGAL::Time_stamper<T1> > C4;
                                           //    with timestamps
 
   typedef Node_2 T3;
@@ -337,7 +337,7 @@ int main()
   {
     std::cerr << "Error timestamper of C3\n"; return 1;
   }
-  if(! std::is_base_of<CGAL::Time_stamper<T2>,
+  if(! std::is_base_of<CGAL::Time_stamper<T1>,
      C4::Time_stamper>::value)
   {
     std::cerr << "Error timestamper of C4\n"; return 1;
diff --git a/Stream_support/include/CGAL/IO/Generic_writer.h b/Stream_support/include/CGAL/IO/Generic_writer.h
index b91a8a5b7f7..e425fc51866 100644
--- a/Stream_support/include/CGAL/IO/Generic_writer.h
+++ b/Stream_support/include/CGAL/IO/Generic_writer.h
@@ -55,7 +55,7 @@ class Generic_writer
     for(std::size_t i=0, end=points.size(); i<end; ++i)
     {
       const typename boost::property_traits<PointMap>::value_type& p = get(point_map, points[i]);
-      m_writer.write_vertex(p.x(), p.y(), p.z());
+      m_writer.write_vertex(to_double(p.x()), to_double(p.y()), to_double(p.z()));
     }
 
     m_writer.write_facet_header();
diff --git a/Stream_support/include/CGAL/IO/PLY/PLY_reader.h b/Stream_support/include/CGAL/IO/PLY/PLY_reader.h
index ee8b18ef59c..c35bc6d4141 100644
--- a/Stream_support/include/CGAL/IO/PLY/PLY_reader.h
+++ b/Stream_support/include/CGAL/IO/PLY/PLY_reader.h
@@ -17,7 +17,7 @@
 #include <CGAL/Kernel_traits.h>
 #include <CGAL/property_map.h>
 
-#include <boost/cstdint.hpp>
+#include <cstdint>
 #include <boost/range/value_type.hpp>
 
 #include <iostream>
diff --git a/Stream_support/include/CGAL/IO/io.h b/Stream_support/include/CGAL/IO/io.h
index d9c2ea7f761..aa7d650e72b 100644
--- a/Stream_support/include/CGAL/IO/io.h
+++ b/Stream_support/include/CGAL/IO/io.h
@@ -183,7 +183,7 @@ class Output_rep
 
 public:
   //! initialize with a const reference to \a t.
-  Output_rep( const T& tt) : t(tt) {}
+  Output_rep( const T& tt, F = {}) : t(tt) {}
   //! perform the output, calls \c operator\<\< by default.
   std::ostream& operator()( std::ostream& os) const { return (os << t); }
 };
@@ -248,7 +248,12 @@ Convenience function to construct an output representation (`Output_rep`) for ty
 Generic IO for type `T` with formatting tag.
 */
 template <class T, class F>
-Output_rep<T,F> oformat( const T& t, F) { return Output_rep<T,F>(t); }
+Output_rep<T,F> oformat( const T& t, F format) {
+  if constexpr (std::is_constructible_v<Output_rep<T,F>, const T&, F>)
+    return Output_rep<T,F>(t, format);
+  else
+    return Output_rep<T,F>(t);
+}
 
 } // namespace IO
 
@@ -990,6 +995,53 @@ inline void read_float_or_quotient(std::istream& is, Rat &z)
 
 } // namespace CGAL
 
+#if CGAL_CAN_USE_CXX20_FORMAT
+#  include <format>
+#  include <sstream>
+
+namespace std {
+
+template <typename T, typename F, typename CharT>
+struct formatter<CGAL::Output_rep<T, F>, CharT> : public std::formatter<std::basic_string<CharT>>
+{
+  constexpr auto parse(std::basic_format_parse_context<CharT>& ctx)
+  {
+    auto it = ctx.begin();
+    const auto end = ctx.end();
+    if(it == end)
+      return it;
+    if(*it != CharT('.')) {
+      if(*it == CharT('}')) return it;
+      throw std::format_error("formatter for CGAL::Output_rep only support precision, like `{:.6}`");
+    }
+    if(++it == end)
+      throw std::format_error("Missing precision");
+    if(*it < CharT('0') || *it > CharT('9'))
+      throw std::format_error("Invalid value for precision");
+    precision = *it - CharT('0');
+    while(++it != end) {
+      if(*it < CharT('0') || *it > CharT('9'))
+        return it;
+      precision = precision * 10 + (*it - CharT('0'));
+    }
+    return it;
+  }
+
+  template <typename FormatContext>
+  auto format(const CGAL::Output_rep<T, F> &rep, FormatContext& ctx) const
+  {
+    std::basic_stringstream<CharT> ss;
+    ss.precision(precision);
+    ss << rep;
+    return std::formatter<std::basic_string<CharT>>::format(ss.str(), ctx);
+  }
+
+  int precision = 17;
+};
+
+} // namespace std
+#endif // CGAL_CAN_USE_CXX20_FORMAT
+
 #include <CGAL/enable_warnings.h>
 
 #endif // CGAL_IO_H
diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h
index 322e6cef1b8..f7c386b9d3f 100644
--- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h
+++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h
@@ -183,7 +183,7 @@ class Triangulation_data_structure_2
   }
 
   Face_handles face_handles() const {
-    return make_prevent_deref_range(faces_begin(),faces_end());
+    return { faces_begin(), faces_end() };
   }
 
   Vertex_iterator vertices_begin() const  {
@@ -195,7 +195,7 @@ class Triangulation_data_structure_2
   }
 
   Vertex_handles vertex_handles() const {
-    return make_prevent_deref_range(vertices_begin(),vertices_end());
+    return { vertices_begin(), vertices_end() };
   }
 
   Edge_iterator edges_begin() const {
diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h
index 6f63f08162d..ca34d9f92c5 100644
--- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h
+++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h
@@ -31,6 +31,9 @@
 #include <limits>
 
 #include <boost/unordered_set.hpp>
+#include <boost/container/flat_set.hpp>
+#include <boost/container/small_vector.hpp>
+#include <boost/iterator/function_output_iterator.hpp>
 #include <CGAL/utility.h>
 #include <CGAL/iterator.h>
 #include <CGAL/STL_Extension/internal/Has_member_visited.h>
@@ -661,7 +664,7 @@ class Triangulation_data_structure_3
 
   Cell_handles cell_handles() const
   {
-    return make_prevent_deref_range(cells_begin(), cells_end());
+    return { cells_begin(), cells_end() };
   }
 
   Cell_iterator raw_cells_begin() const
@@ -720,7 +723,7 @@ class Triangulation_data_structure_3
 
   Vertex_handles vertex_handles() const
   {
-    return make_prevent_deref_range(vertices_begin(), vertices_end());
+    return { vertices_begin(), vertices_end() };
   }
 
   // CIRCULATOR METHODS
@@ -802,7 +805,7 @@ class Triangulation_data_structure_3
   {
         CGAL_precondition(dimension() == 3);
 
-        std::stack<Cell_handle> cell_stack;
+        std::stack<Cell_handle, boost::container::small_vector<Cell_handle, 128>> cell_stack;
         cell_stack.push(d);
         d->tds_data().mark_in_conflict();
         *it.first++ = d;
@@ -828,13 +831,16 @@ class Triangulation_data_structure_3
         return it;
   }
 
-  template <class IncidentFacetIterator>
+  template <class IncidentFacetIterator, typename CellsContainers>
   void
   incident_cells_3_threadsafe(Vertex_handle v, Cell_handle d,
-                              std::vector<Cell_handle> &cells,
+                              CellsContainers &cells,
                               IncidentFacetIterator facet_it) const
   {
-    boost::unordered_set<Cell_handle, Handle_hash_function> found_cells;
+    boost::container::flat_set<Cell_handle,
+                               std::less<>,
+                               boost::container::small_vector<Cell_handle, 128>> found_cells;
+    // boost::unordered_set<Cell_handle, Handle_hash_function> found_cells;
 
     cells.push_back(d);
     found_cells.insert(d);
@@ -1381,20 +1387,16 @@ class Triangulation_data_structure_3
 
     Visitor visit(v, output, this, f);
 
-    std::vector<Cell_handle> tmp_cells;
-    tmp_cells.reserve(64);
+    boost::container::small_vector<Cell_handle, 128> tmp_cells;
     if ( dimension() == 3 )
     incident_cells_3(v, v->cell(), std::make_pair(std::back_inserter(tmp_cells), visit.facet_it()));
     else
     incident_cells_2(v, v->cell(), std::back_inserter(tmp_cells));
 
-    typename std::vector<Cell_handle>::iterator cit;
-    for(cit = tmp_cells.begin();
-        cit != tmp_cells.end();
-        ++cit)
+    for(auto c : tmp_cells)
     {
-      (*cit)->tds_data().clear();
-      visit(*cit);
+      c->tds_data().clear();
+      visit(c);
     }
 
     return visit.result();
@@ -1413,20 +1415,16 @@ class Triangulation_data_structure_3
 
     Visitor visit(v, output, this, f);
 
-    std::vector<Cell_handle> tmp_cells;
-    tmp_cells.reserve(64);
+    boost::container::small_vector<Cell_handle, 128> tmp_cells;
     if ( dimension() == 3 )
       incident_cells_3_threadsafe(
         v, v->cell(), tmp_cells, visit.facet_it());
     else
       incident_cells_2(v, v->cell(), std::back_inserter(tmp_cells));
 
-    typename std::vector<Cell_handle>::iterator cit;
-    for(cit = tmp_cells.begin();
-        cit != tmp_cells.end();
-        ++cit)
+    for(auto c : tmp_cells)
     {
-      visit(*cit);
+      visit(c);
     }
 
     return visit.result();
@@ -2059,29 +2057,67 @@ is_edge(Vertex_handle u, Vertex_handle v,
         Cell_handle &c, int &i, int &j) const
   // returns false when dimension <1 or when indices wrong
 {
-    CGAL_expensive_precondition( is_vertex(u) && is_vertex(v) );
+  CGAL_expensive_precondition(is_vertex(u) && is_vertex(v));
 
-    if (u==v)
-        return false;
+  if(u == v)
+    return false;
 
-    std::vector<Cell_handle> cells;
-    cells.reserve(64);
-    incident_cells(u, std::back_inserter(cells));
+  if(dimension() == 3) {
+    auto d = u->cell();
+    boost::container::small_vector<Cell_handle, 128> cells;
+    cells.emplace_back(d);
+    d->tds_data().mark_in_conflict();
 
-    for (typename std::vector<Cell_handle>::iterator cit = cells.begin();
-              cit != cells.end(); ++cit)
-        if ((*cit)->has_vertex(v, j)) {
-            c = *cit;
-            i = c->index(u);
-            return true;
+    auto cleanup_tds_data = make_scope_exit([&] {
+      for(auto c : cells) {
+        c->tds_data().clear();
+      }
+    });
+
+    int head = 0;
+    int tail = 1;
+    do {
+      Cell_handle ch = cells[head];
+
+      for(j = 0; j < 4; ++j) { // use parameter j on purpose
+        if(ch->vertex(j) == v) {
+          c = ch;
+          i = ch->index(u);
+          return true;
         }
+        if(ch->vertex(j) == u)
+          continue;
+        Cell_handle next = ch->neighbor(j);
+        if(!next->tds_data().is_clear())
+          continue;
+        cells.emplace_back(next);
+        ++tail;
+        next->tds_data().mark_in_conflict();
+      }
+      ++head;
+    } while(head != tail);
     return false;
+  }
+
+  bool edge_found = false;
+  // try {
+  incident_cells_threadsafe(u, boost::make_function_output_iterator([&](Cell_handle ch) {
+                              if(ch->has_vertex(v, j)) {
+                                c = ch;
+                                i = c->index(u);
+                                // throw true;
+                                edge_found = true;
+                              }
+                            }));
+  // } catch(bool b) {
+  //     result = b;
+  // }
+
+  return edge_found;
 }
 
 template <class Vb, class Cb, class Ct>
-bool
-Triangulation_data_structure_3<Vb,Cb,Ct>::
-is_edge(Vertex_handle u, Vertex_handle v) const
+bool Triangulation_data_structure_3<Vb, Cb, Ct>::is_edge(Vertex_handle u, Vertex_handle v) const
 {
     Cell_handle c;
     int i, j;
@@ -3573,6 +3609,12 @@ is_valid(bool verbose, int level ) const
       size_type cell_count;
       if ( ! count_cells(cell_count,verbose,level) )
         return false;
+      if( number_of_cells() != cell_count ) {
+        if (verbose)
+          std::cerr << "wrong number of cells" << std::endl;
+        CGAL_assertion(false);
+        return false;
+      }
       size_type edge_count;
       if ( ! count_edges(edge_count,verbose,level) )
           return false;
diff --git a/TDS_3/include/CGAL/Triangulation_simplex_3.h b/TDS_3/include/CGAL/Triangulation_simplex_3.h
index 0754fb021c5..d00422df1ba 100644
--- a/TDS_3/include/CGAL/Triangulation_simplex_3.h
+++ b/TDS_3/include/CGAL/Triangulation_simplex_3.h
@@ -19,6 +19,7 @@
 
 #include <CGAL/assertions.h>
 #include <algorithm>
+#include <CGAL/IO/io.h>
 
 namespace CGAL {
 
@@ -280,6 +281,57 @@ operator<< (std::ostream& os,
   return os;
 }
 
+template < typename TriangulationDataStructure_3, typename Tag >
+struct Output_rep<Triangulation_simplex_3<TriangulationDataStructure_3>, Tag >
+{
+  using TDS = TriangulationDataStructure_3;
+  using Simplex = Triangulation_simplex_3<TriangulationDataStructure_3>;
+  using Vertex_handle = typename Simplex::Vertex_handle;
+  using Edge = typename Simplex::Edge;
+  using Facet = typename Simplex::Facet;
+  using Cell_handle = typename Simplex::Cell_handle;
+
+  Simplex simplex;
+  Tag tag;
+
+  std::ostream& operator()(std::ostream& os) const {
+    auto display_vert = [&](auto v) {
+      return CGAL::IO::oformat(v, tag);
+    };
+    switch(simplex.dimension()) {
+      case 0: {
+        os << "vertex " << display_vert(static_cast<Vertex_handle>(simplex));
+        break;
+      }
+      case 1: {
+        const auto [c, index1, index2] = static_cast<Edge>(simplex);
+        os << "edge "
+           << display_vert(c->vertex(index1)) << " - "
+           << display_vert(c->vertex(index2));
+        break;
+      }
+      case 2: {
+        const auto [c, index] = static_cast<Facet>(simplex);
+        os << "facet "
+           << display_vert(c->vertex(TDS::vertex_triple_index(index, 0))) << " - "
+           << display_vert(c->vertex(TDS::vertex_triple_index(index, 1))) << " - "
+           << display_vert(c->vertex(TDS::vertex_triple_index(index, 2)));
+        break;
+      }
+      case 3: {
+        const auto c = static_cast<Cell_handle>(simplex);
+        os << "cell "
+           << display_vert(c->vertex(0)) << " - "
+           << display_vert(c->vertex(1)) << " - "
+           << display_vert(c->vertex(2)) << " - "
+           << display_vert(c->vertex(3));
+        break;
+      }
+      default: CGAL_assume(false);
+    }
+    return os;
+  }
+};
 
 } //namespace CGAL
 
diff --git a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h
index 0d810e92288..68d24483b34 100644
--- a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h
+++ b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h
@@ -144,6 +144,19 @@ according to the
 */
 typedef unspecified_type Compare_y_2;
 
+/*!
+A function object that lexicographically compares two points by their Cartesian
+coordinates.
+It provides the operator:
+
+`Comparison_result operator()(Point p, Point q)`
+
+which returns
+(`SMALLER, EQUAL` or `LARGER`)
+according to the lexicographical order of points `p` and `q`.
+*/
+typedef unspecified_type Compare_xy_2;
+
 /*!
 A function object to compute the orientation of three points.
 
@@ -245,6 +258,11 @@ Compare_y_2 compare_y_2_object();
 
 /*!
 
+*/
+Compare_xy_2 compare_xy_2_object();
+
+/*!
+
 */
 Orientation_2 orientation_2_object();
 
diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h
index 884644147f1..90d6448f0e5 100644
--- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h
+++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h
@@ -37,28 +37,6 @@
 #include <boost/mpl/has_xxx.hpp>
 #include <boost/iterator/filter_iterator.hpp>
 
-#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS
-#  include <CGAL/IO/io.h>
-#  include <CGAL/Compact_container.h>
-#  include <iostream>
-namespace CGAL {
-
-struct With_point_tag {};
-
-template <class DSC, bool Const>
-struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_point_tag>
-  : public Output_rep<CGAL::internal::CC_iterator<DSC, Const>>
-{
-  using Base = Output_rep<CGAL::internal::CC_iterator<DSC, Const>>;
-  using Base::Base;
-
-  std::ostream& operator()(std::ostream& out) const {
-    return Base::operator()(out) << "= " << this->it->point();
-  }
-};
-} // namespace CGAL
-#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
-
 namespace CGAL {
 
 struct No_constraint_intersection_tag{};
@@ -367,13 +345,9 @@ insert_constraint(Vertex_handle  vaa, Vertex_handle vbb, OutputIterator out)
     // if the segment (or a subpart of the segment) that we are trying to constraint is already
     // present in the triangulation and is already marked as constrained,
     // then this is an intersection
-    if(std::is_same<Itag, No_constraint_intersection_tag>::value) {
-      if(dimension() == 1) {
-        if(fr->is_constrained(2))
-          throw Intersection_of_constraints_exception();
-      } else {
-        if(fr->is_constrained(i))
-          throw Intersection_of_constraints_exception();
+    if constexpr (std::is_same_v<Itag, No_constraint_intersection_tag>) {
+      if(fr->is_constrained(dimension() == 1 ? 2 : i)) {
+        throw Intersection_of_constraints_exception();
       }
     }
 
@@ -749,7 +723,7 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li)
   }
   if ( lt == Triangulation::EDGE && loc->is_constrained(li) )
   {
-    if(std::is_same<Itag, No_constraint_intersection_tag>::value)
+    if constexpr (std::is_same_v<Itag, No_constraint_intersection_tag>)
       throw Intersection_of_constraints_exception();
 
     insert_in_constrained_edge = true;
@@ -851,7 +825,7 @@ insert_constraint(Vertex_handle  vaa, Vertex_handle vbb)
               << " , " << display_vertex(vbb)
               << " ) remaining stack size: "
               << stack.size() << '\n';
-    CGAL_assertion(this->is_valid());
+    CGAL_assertion(this->is_valid(true));
 #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS
     Vertex_handle vi;
 
@@ -862,13 +836,9 @@ insert_constraint(Vertex_handle  vaa, Vertex_handle vbb)
       // if the segment (or a subpart of the segment) that we are trying to constraint is already
       // present in the triangulation and is already marked as constrained,
       // then this is an intersection
-      if(std::is_same<Itag, No_constraint_intersection_tag>::value) {
-        if(dimension() == 1) {
-          if(fr->is_constrained(2))
-            throw Intersection_of_constraints_exception();
-        } else {
-          if(fr->is_constrained(i))
-            throw Intersection_of_constraints_exception();
+      if constexpr (std::is_same_v<Itag, No_constraint_intersection_tag>) {
+        if(fr->is_constrained(dimension() == 1 ? 2 : i)) {
+          throw Intersection_of_constraints_exception();
         }
       }
 
diff --git a/Triangulation_2/include/CGAL/Regular_triangulation_2.h b/Triangulation_2/include/CGAL/Regular_triangulation_2.h
index 3353b7d7603..54938928e5c 100644
--- a/Triangulation_2/include/CGAL/Regular_triangulation_2.h
+++ b/Triangulation_2/include/CGAL/Regular_triangulation_2.h
@@ -162,7 +162,7 @@ class Regular_triangulation_2
     Self & operator--() { Base::operator--(); return *this; }
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
-    operator Vertex_handle() const { return Base::base(); }
+    operator const Vertex_handle&() const { return Base::base(); }
   };
 
   typedef Iterator_range<Prevent_deref<All_vertices_iterator> > All_vertex_handles;
@@ -179,10 +179,11 @@ class Regular_triangulation_2
     Self & operator--() { Base::operator--(); return *this; }
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
-    operator Vertex_handle() const { return Base::base(); }
+    operator const Vertex_handle&() const { return Base::base(); }
  };
 
-  typedef Iterator_range<Prevent_deref<Finite_vertices_iterator> > Finite_vertex_handles;
+  typedef Iterator_range<Prevent_deref<Finite_vertices_iterator,
+                                       const Vertex_handle&>> Finite_vertex_handles;
 
   class Hidden_vertices_iterator :
     public Filter_iterator<Finite_vib, Unhidden_tester>
@@ -196,10 +197,11 @@ class Regular_triangulation_2
     Self & operator--() { Base::operator--(); return *this; }
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
-    operator Vertex_handle() const { return Base::base(); }
+    operator const Vertex_handle&() const { return Base::base(); }
  };
 
-  typedef Iterator_range<Prevent_deref<Hidden_vertices_iterator> > Hidden_vertex_handles;
+  typedef Iterator_range<Prevent_deref<Hidden_vertices_iterator,
+                                       const Vertex_handle&>> Hidden_vertex_handles;
 
  //for backward compatibility
   typedef Finite_faces_iterator                Face_iterator;
@@ -2233,7 +2235,7 @@ typename Regular_triangulation_2<Gt,Tds>::Finite_vertex_handles
 Regular_triangulation_2<Gt,Tds>::
 finite_vertex_handles() const
 {
-  return make_prevent_deref_range(finite_vertices_begin(),finite_vertices_end());
+    return { finite_vertices_begin(), finite_vertices_end() };
 }
 
 template < class Gt, class Tds >
@@ -2260,7 +2262,7 @@ typename Regular_triangulation_2<Gt,Tds>::Hidden_vertex_handles
 Regular_triangulation_2<Gt,Tds>::
 hidden_vertex_handles() const
 {
-  return make_prevent_deref_range(hidden_vertices_begin(),hidden_vertices_end());
+  return { hidden_vertices_begin(), hidden_vertices_end() };
 }
 
 template < class Gt, class Tds >
diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h
index c0f2c7ba50e..433ea5cb5af 100644
--- a/Triangulation_2/include/CGAL/Triangulation_2.h
+++ b/Triangulation_2/include/CGAL/Triangulation_2.h
@@ -172,7 +172,7 @@ class Triangulation_2
     Self & operator--() { Base::operator--(); return *this; }
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
-    operator Vertex_handle() const { return Base::base(); }
+    operator const Vertex_handle&() const { return Base::base(); }
   };
 
   class Finite_faces_iterator
@@ -187,7 +187,7 @@ class Triangulation_2
     Self & operator--() { Base::operator--(); return *this; }
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
-    operator Face_handle() const { return Base::base(); }
+    operator const Face_handle&() const { return Base::base(); }
   };
 
   typedef Filter_iterator<All_edges_iterator,
@@ -214,8 +214,10 @@ class Triangulation_2
   typedef typename Tds::Vertex_handles         All_vertex_handles;
   typedef typename Tds::Edges                  All_edges;
 
-  typedef Iterator_range<Prevent_deref<Finite_faces_iterator> >    Finite_face_handles;
-  typedef Iterator_range<Prevent_deref<Finite_vertices_iterator> > Finite_vertex_handles;
+  typedef Iterator_range<Prevent_deref<Finite_faces_iterator,
+                                       const Face_handle&>>   Finite_face_handles;
+  typedef Iterator_range<Prevent_deref<Finite_vertices_iterator,
+                                       const Vertex_handle&>> Finite_vertex_handles;
   typedef Iterator_range<Finite_edges_iterator>                    Finite_edges;
   typedef Iterator_range<Point_iterator>                           Points;
 
@@ -3267,7 +3269,7 @@ typename Triangulation_2<Gt, Tds>::Finite_face_handles
 Triangulation_2<Gt, Tds>::
 finite_face_handles() const
 {
-  return make_prevent_deref_range(finite_faces_begin(),finite_faces_end());
+  return { finite_faces_begin(), finite_faces_end() };
 }
 
 template <class Gt, class Tds >
@@ -3296,7 +3298,7 @@ typename Triangulation_2<Gt, Tds>::Finite_vertex_handles
 Triangulation_2<Gt, Tds>::
 finite_vertex_handles() const
 {
-  return make_prevent_deref_range(finite_vertices_begin(),finite_vertices_end());
+  return { finite_vertices_begin(), finite_vertices_end() };
 }
 
 template <class Gt, class Tds >
@@ -3671,13 +3673,8 @@ Comparison_result
 Triangulation_2<Gt, Tds>::
 compare_xy(const Point& p, const Point& q) const
 {
-  Comparison_result res = geom_traits().compare_x_2_object()(construct_point(p),
-                                                             construct_point(q));
-  if(res == EQUAL){
-    return geom_traits().compare_y_2_object()(construct_point(p),
-                                              construct_point(q));
-  }
-  return res;
+  return geom_traits().compare_xy_2_object()(construct_point(p),
+                                             construct_point(q));
 }
 
 template <class Gt, class Tds >
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 21144872845..73a7db231ac 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
@@ -163,7 +163,7 @@ class Polyline_constraint_hierarchy_2
     Vertex_it    vertices_begin()const { return enclosing->skip_begin();}
     Vertex_it    current()const {return pos;}
     Vertex_it    vertices_end()const {return enclosing->skip_end();}
-    Constraint_id  id() { return enclosing; }
+    Constraint_id  id()const { return enclosing; }
     std::size_t    number_of_vertices() const {return enclosing->skip_size(); }
   };
 
@@ -221,6 +221,7 @@ class Polyline_constraint_hierarchy_2
   std::size_t number_of_enclosing_constraints(T va, T vb) const;
   Context_iterator contexts_begin(T va, T vb) const;
   Context_iterator contexts_end(T va, T vb) const;
+  Iterator_range<Context_iterator> contexts_range(T va, T vb) const;
   std::size_t number_of_constraints() const  { return constraint_set.size();}
   std::size_t number_of_subconstraints()const {return sc_to_c_map.size();}
 
@@ -488,6 +489,15 @@ contexts_end(T va, T vb) const
    return last;
 }
 
+template <class T, class Compare, class Point>
+auto
+Polyline_constraint_hierarchy_2<T,Compare,Point>::
+contexts_range(T va, T vb) const -> Iterator_range<Context_iterator> {
+  Context_iterator first, last;
+  if( !get_contexts(va,vb,first,last)) return { first, first };
+  else return { first, last };
+}
+
 template <class T, class Compare, class Point>
 void
 Polyline_constraint_hierarchy_2<T,Compare,Point>::
diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h
index 29e66a38e1b..bb3087c11ef 100644
--- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h
+++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h
@@ -188,6 +188,19 @@ class Triangulation_test_Compare_y_2{
     }
 };
 
+class Triangulation_test_Compare_xy_2{
+public:
+  typedef Triangulation_test_point  Point;
+  CGAL::Comparison_result operator()( const Point& p, const Point&  q) const
+    {
+      if (p.test_x() < q.test_x()) return CGAL::SMALLER;
+      if (p.test_x() > q.test_x()) return CGAL::LARGER;
+      if (p.test_y() < q.test_y()) return CGAL::SMALLER;
+      if (p.test_y() > q.test_y()) return CGAL::LARGER;
+      else return CGAL::EQUAL;
+    }
+};
+
 class Triangulation_test_Orientation_2
 {
 public:
@@ -416,6 +429,7 @@ class _Triangulation_test_traits {
   typedef Triangulation_test_Less_y_2       Less_y_2;
   typedef Triangulation_test_Compare_x_2    Compare_x_2;
   typedef Triangulation_test_Compare_y_2    Compare_y_2;
+  typedef Triangulation_test_Compare_xy_2   Compare_xy_2;
   typedef Triangulation_test_Orientation_2  Orientation_2;
   typedef Triangulation_test_Side_of_oriented_circle_2
                                              Side_of_oriented_circle_2;
@@ -450,6 +464,10 @@ class _Triangulation_test_traits {
   compare_y_2_object() const
     { return Compare_y_2();}
 
+  Compare_xy_2
+  compare_xy_2_object() const
+    { return Compare_xy_2();}
+
   Orientation_2
   orientation_2_object() const
     { return Orientation_2();}
diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h
index 12e92b65447..5b2df86f1e0 100644
--- a/Triangulation_3/include/CGAL/Triangulation_3.h
+++ b/Triangulation_3/include/CGAL/Triangulation_3.h
@@ -495,7 +495,7 @@ class Triangulation_3
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
 
-    operator Cell_handle() const { return Base::base(); }
+    operator const Cell_handle&() const { return Base::base(); }
   };
 
   // We derive in order to add a conversion to handle.
@@ -514,11 +514,13 @@ class Triangulation_3
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
 
-    operator Vertex_handle() const { return Base::base(); }
+    operator const Vertex_handle&() const { return Base::base(); }
   };
 
-  typedef Iterator_range<Prevent_deref<Finite_cells_iterator> >    Finite_cell_handles;
-  typedef Iterator_range<Prevent_deref<Finite_vertices_iterator> > Finite_vertex_handles;
+  typedef Iterator_range<Prevent_deref<Finite_cells_iterator,
+                                       const Cell_handle&> >         Finite_cell_handles;
+  typedef Iterator_range<Prevent_deref<Finite_vertices_iterator,
+                                       const Vertex_handle&> >       Finite_vertex_handles;
 
   typedef Filter_iterator<Edge_iterator, Infinite_tester>     Finite_edges_iterator;
   typedef Filter_iterator<Facet_iterator, Infinite_tester>    Finite_facets_iterator;
@@ -529,7 +531,8 @@ class Triangulation_3
   typedef Triangulation_segment_cell_iterator_3<Self>    Segment_cell_iterator;
   typedef Triangulation_segment_simplex_iterator_3<Self> Segment_simplex_iterator;
 
-  typedef Iterator_range<Prevent_deref<Segment_cell_iterator> >    Segment_traverser_cell_handles;
+  typedef Iterator_range<Prevent_deref<Segment_cell_iterator,
+                                       const Cell_handle&> >    Segment_traverser_cell_handles;
   typedef Iterator_range<Segment_simplex_iterator> Segment_traverser_simplices;
 
 private:
@@ -899,6 +902,7 @@ class Triangulation_3
                Cell_handle& c, int& i, int& j) const;
   bool is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w,
                 Cell_handle& c, int& i, int& j, int& k) const;
+  bool is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w) const;
   bool is_cell(Cell_handle c) const;
   bool is_cell(Vertex_handle u, Vertex_handle v,
                Vertex_handle w, Vertex_handle t,
@@ -1801,7 +1805,7 @@ class Triangulation_3
 
   Finite_cell_handles finite_cell_handles() const
   {
-    return make_prevent_deref_range(finite_cells_begin(), finite_cells_end());
+    return {finite_cells_begin(), finite_cells_end()};
   }
 
 
@@ -1831,7 +1835,7 @@ class Triangulation_3
 
   Finite_vertex_handles finite_vertex_handles() const
   {
-    return make_prevent_deref_range(finite_vertices_begin(), finite_vertices_end());
+    return {finite_vertices_begin(), finite_vertices_end()};
   }
 
   Vertex_iterator vertices_begin() const { return _tds.vertices_begin(); }
@@ -2266,15 +2270,13 @@ class Triangulation_3
   Segment_traverser_cell_handles segment_traverser_cell_handles(Vertex_handle vs,
                                                                 Vertex_handle vt) const
   {
-    return make_prevent_deref_range(segment_traverser_cells_begin(vs, vt),
-                                    segment_traverser_cells_end());
+    return {segment_traverser_cells_begin(vs, vt), segment_traverser_cells_end()};
   }
   Segment_traverser_cell_handles segment_traverser_cell_handles(const Point& ps,
                                                                 const Point& pt,
                                                                 Cell_handle hint = Cell_handle()) const
   {
-    return make_prevent_deref_range(segment_traverser_cells_begin(ps, pt, hint),
-                                    segment_traverser_cells_end());
+    return {segment_traverser_cells_begin(ps, pt, hint), segment_traverser_cells_end()};
   }
 
   //// Segment Simplex Iterator
@@ -2714,6 +2716,16 @@ is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w,
   return _tds.is_facet(u, v, w, c, i, j, k);
 }
 
+template < class GT, class Tds, class Lds >
+bool
+Triangulation_3<GT,Tds,Lds>::
+is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w) const
+{
+  Cell_handle c;
+  int i; int j; int k;
+  return _tds.is_facet(u, v, w, c, i, j, k);
+}
+
 template < class GT, class Tds, class Lds >
 inline
 bool
@@ -4976,35 +4988,22 @@ create_triangulation_inner_map(const Triangulation& t,
                                const Vertex_handle_unique_hash_map& vmap,
                                bool all_cells) {
   Vertex_triple_Facet_map inner_map;
-
-  if(all_cells)
-  {
-    for(All_cells_iterator it = t.all_cells_begin(),
-                           end = t.all_cells_end(); it != end; ++it)
-    {
-      for(unsigned int index=0; index < 4; index++)
-      {
-        Facet f = std::pair<Cell_handle,int>(it,index);
-        Vertex_triple vt_aux = make_vertex_triple(f);
-        Vertex_triple vt{vmap[vt_aux[0]], vmap[vt_aux[2]], vmap[vt_aux[1]]};
-        make_canonical_oriented_triple(vt);
-        inner_map[vt] = f;
-      }
-    }
-  } else
-  {
-    for(Finite_cells_iterator it = t.finite_cells_begin(),
-                              end = t.finite_cells_end(); it != end; ++it)
-    {
-      for(unsigned int index=0; index < 4; index++)
-      {
-        Facet f = std::pair<Cell_handle,int>(it,index);
+  auto create_triangulation_inner_map_aux = [&](const auto& cells_range) {
+    for(auto ch : cells_range) {
+      for(unsigned int index = 0; index < 4; index++) {
+        Facet f = std::pair<Cell_handle, int>(ch, index);
         Vertex_triple vt_aux = make_vertex_triple(f);
         Vertex_triple vt{vmap[vt_aux[0]], vmap[vt_aux[2]], vmap[vt_aux[1]]};
         make_canonical_oriented_triple(vt);
         inner_map[vt] = f;
       }
     }
+  };
+
+  if(all_cells) {
+    create_triangulation_inner_map_aux(t.all_cell_handles());
+  } else {
+    create_triangulation_inner_map_aux(t.finite_cell_handles());
   }
   return inner_map;
 }
@@ -5095,7 +5094,7 @@ Triangulation_3<Gt,Tds,Lds>::
 copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap,
                              Vertex_triple_Facet_map&& outer_map,
                              const Vertex_triple_Facet_map& inner_map,
-                             OutputItCells fit)
+                             OutputItCells cit)
 {
   while(! outer_map.empty())
   {
@@ -5109,20 +5108,20 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap,
       // because the infinite vertices are different
     }
 
-    typename Vertex_triple_Facet_map::value_type o_vt_f_pair = *oit;
+    const auto vertex_triple = oit->first;
+    const auto facet = oit->second;
     outer_map.erase(oit);
-    Cell_handle o_ch = o_vt_f_pair.second.first;
-    unsigned int o_i = o_vt_f_pair.second.second;
+    const Cell_handle o_ch = facet.first;
+    const unsigned int o_i = facet.second;
 
-    auto iit = inner_map.find(o_vt_f_pair.first);
+    const auto iit = inner_map.find(vertex_triple);
     CGAL_assertion(iit != inner_map.end());
-    typename Vertex_triple_Facet_map::value_type i_vt_f_pair = *iit;
-    Cell_handle i_ch = i_vt_f_pair.second.first;
-    unsigned int i_i = i_vt_f_pair.second.second;
+    const auto i_facet = iit->second;
+    const Cell_handle i_ch = i_facet.first;
+    const unsigned int i_i = i_facet.second;
 
     // Create a new cell and glue it to the outer surface
     Cell_handle new_ch = tds().create_cell();
-    *fit++ = new_ch;
     new_ch->set_vertices(vmap[i_ch->vertex(0)], vmap[i_ch->vertex(1)],
                          vmap[i_ch->vertex(2)], vmap[i_ch->vertex(3)]);
 
@@ -5132,12 +5131,14 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap,
     for(int j=0; j<4; j++)
      new_ch->vertex(j)->set_cell(new_ch);
 
+    *cit++ = new_ch;
+
     // For the other faces check, if they can also be glued
     for(unsigned int index = 0; index < 4; index++)
     {
       if(index != i_i)
       {
-        Facet f = std::pair<Cell_handle, int>(new_ch, index);
+        Facet f{new_ch, index};
         Vertex_triple vt = make_vertex_triple(f);
         make_canonical_oriented_triple(vt);
         std::swap(vt[1], vt[2]);
@@ -5151,9 +5152,9 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap,
         else
         {
           // glue the faces
-          typename Vertex_triple_Facet_map::value_type o_vt_f_pair2 = *oit2;
-          Cell_handle o_ch2 = o_vt_f_pair2.second.first;
-          int o_i2 = o_vt_f_pair2.second.second;
+          const auto facet2 = oit2->second;
+          const Cell_handle o_ch2 = facet2.first;
+          const int o_i2 = facet2.second;
           o_ch2->set_neighbor(o_i2, new_ch);
           new_ch->set_neighbor(index, o_ch2);
           outer_map.erase(oit2);
@@ -5161,7 +5162,7 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap,
       }
     }
   }
-  return fit;
+  return cit;
 }
 
 
diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h
index e588e7f6cf9..2f75230ebbd 100644
--- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h
+++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h
@@ -505,9 +505,15 @@ Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& pre
         continue;
     }
     const Point* const backup_vert_li = std::exchange(vert[li], &_target);
-
+    bool op_li_is_null = false;
+    if(_t_vertex != Vertex_handle()) {
+      for(int i = 0; i < 4; ++i) {
+        if(li == i) continue;
+        if(cur_cell->vertex(i) == _t_vertex) op_li_is_null = true;
+      }
+    }
     // Check if the target is on the opposite side of the supporting plane.
-    op[li] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]);
+    op[li] = op_li_is_null ? ZERO : _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]);
     if(op[li] == POSITIVE)
         pos += li;
     if(op[li] != NEGATIVE) {
@@ -597,7 +603,7 @@ Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& pre
   // The target lies inside this cell.
   CGAL_assertion( incell );
   return {
-    [&]() -> Simplex {
+    std::invoke([&]() -> Simplex {
       switch( op[0] + op[1] + op[2] + op[3] ) {
       case 4:
         CGAL_assertion( pos == 6 );
@@ -625,7 +631,7 @@ Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& pre
       default:
         CGAL_unreachable();
       }
-    }(),
+    }),
     { Cell_handle() }
   };
 }
@@ -748,7 +754,7 @@ template < class Tr, class Inc >
 void Triangulation_segment_cell_iterator_3<Tr,Inc>::
 walk_to_next_2()
 {
-    std::array<Point*, 3> vert
+    const std::array<const Point*, 3> vert
               = { &(cell()->vertex(0)->point()),
                   &(cell()->vertex(1)->point()),
                   &(cell()->vertex(2)->point()) };
diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h
index c098ec429d3..6f25e793fda 100644
--- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h
+++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h
@@ -328,7 +328,7 @@ class Triangulation_segment_cell_iterator_3
     //  provides a conversion operator.
     /*         \return a handle to the current cell.
          */
-    operator Cell_handle() const
+    operator const Cell_handle&() const
     {
       return _cur.cell;
     }
diff --git a/Triangulation_3/test/Triangulation_3/data/1435440-min1.off b/Triangulation_3/test/Triangulation_3/data/1435440-min1.off
new file mode 100644
index 00000000000..ebaac7effc6
--- /dev/null
+++ b/Triangulation_3/test/Triangulation_3/data/1435440-min1.off
@@ -0,0 +1,44 @@
+OFF
+24 16 0
+
+123.67813110351562 60.241893768310547 65.796310424804688
+120.50373840332031 57.575332641601562 65.796310424804688
+120.533935546875 57.536079406738281 39.293754577636719
+115.67936706542969 54.544418334960938 16.005954742431641
+117.02452850341797 55.327865600585938 16.005954742431641
+117.08579254150391 55.232322692871094 21.716342926025391
+118.41075134277344 56.176109313964844 18.36799430847168
+118.40937805175781 56.175144195556641 18.36907958984375
+118.29840850830078 56.096733093261719 18.45704460144043
+118.2930908203125 56.092964172363281 18.462148666381836
+118.28346252441406 56.086151123046875 18.471376419067383
+118.189697265625 56.019577026367188 18.57948112487793
+118.18498229980469 56.016223907470703 18.584924697875977
+118.10399627685547 55.958229064941406 18.713644027709961
+117.99317169189453 55.876365661621094 19.02931022644043
+117.99261474609375 55.875930786132812 19.032327651977539
+117.98808288574219 55.872333526611328 19.057277679443359
+117.97309875488281 55.859172821044922 19.2037353515625
+117.97169494628906 55.857933044433594 19.217502593994141
+137.00740051269531 110.97613525390625 65.796310424804688
+137.4010009765625 109.5654296875 72.631622314453125
+136.79624938964844 110.9072265625 90.521072387695312
+117.75778198242188 56.629554748535156 18.515251159667969
+117.81118774414062 56.667350769042969 18.465158462524414
+3  0 1 2
+3  3 4 5
+3  4 6 7
+3  4 7 8
+3  8 9 4
+3  4 9 10
+3  4 10 11
+3  11 12 4
+3  4 12 13
+3  4 14 15
+3  4 15 16
+3  16 17 4
+3  4 17 18
+3  20 19 21
+3  22 11 10
+3  22 10 23
+
diff --git a/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h b/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h
index 8b3fb4f448e..35c2ef8d7e0 100644
--- a/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h
+++ b/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h
@@ -262,7 +262,7 @@ class Triangulation_on_sphere_2
     Self& operator--() { Base::operator--(); return *this; }
     Self operator++(int) { Self tmp(*this); ++(*this); return tmp; }
     Self operator--(int) { Self tmp(*this); --(*this); return tmp; }
-    operator const Face_handle() const { return Base::base(); }
+    operator const Face_handle&() const { return Base::base(); }
   };
 
   typedef Iterator_range<Prevent_deref<Vertices_iterator> >          Vertex_handles;
@@ -275,7 +275,7 @@ class Triangulation_on_sphere_2
   // solid edges: both incident faces are solid
   typedef Filter_iterator<All_edges_iterator, Ghost_tester>          Solid_edges_iterator;
   typedef Iterator_range<Solid_edges_iterator>                       Solid_edges;
-  typedef Iterator_range<Prevent_deref<Solid_faces_iterator> >       Solid_face_handles;
+  typedef Iterator_range<Prevent_deref<Solid_faces_iterator, const Face_handle&>> Solid_face_handles;
 
   typedef Project_point<Vertex>                                      Pt_proj;
   typedef boost::transform_iterator<Pt_proj, Vertices_iterator>      Point_iterator;
@@ -321,7 +321,7 @@ class Triangulation_on_sphere_2
 
   Solid_face_handles solid_faces() const
   {
-    return make_prevent_deref_range(solid_faces_begin(), solid_faces_end());
+    return { solid_faces_begin(), solid_faces_end() };
   }
 
   Solid_edges_iterator solid_edges_begin() const
diff --git a/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp b/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp
index e3c66570792..06f8ce3c290 100644
--- a/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp
+++ b/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp
@@ -98,6 +98,12 @@ int main(int, char**)
   assert(sfs.size() == 4);
   assert(tr.number_of_solid_faces() + tr.number_of_ghost_faces() == tr.number_of_faces());
 
+  Tr::Face_handle fh = *tr.solid_faces().begin();
+  for(auto f: tr.solid_faces()) {
+    assert(f == fh);
+    break;
+  }
+
   Tr::Points pts = tr.points();
   assert(pts.size() == tr.number_of_vertices() && pts.size() == 5);