From b56cdcb743465a3c9f4fdff83ca6230b76a1763f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 11:23:37 +0100 Subject: [PATCH] Add move-semantic to CGAL (non-periodic) 3D triangulations - For `Triangulation_3`, the rule-of-zero cannot be used, because of the infinite vertex. A special copy-constructor and copy-assignment operators are required. But one can `= default the move-constructor and move-assignment operator, as well as the destructor. - For `Delaunay_triangulation_3`, the rule-of-zero is sufficient. Nothing to do. - For `Regular_triangulation_3`, the `hidden_point_visitor` data member is a function that is constructed with the `this` pointer, so the rule-of-zero cannot be used. Probably the move-constructor and move-assignment operator could be explicitly defaulted. --- ...angulation_cell_base_with_circumcenter_3.h | 15 +++++++++++ .../include/CGAL/Regular_triangulation_3.h | 27 ++++++++++++++++--- .../include/CGAL/Triangulation_3.h | 21 ++++++++------- .../include/CGAL/_test_cls_delaunay_3.h | 6 +++++ .../include/CGAL/_test_cls_regular_3.h | 7 +++++ .../include/CGAL/_test_cls_triangulation_3.h | 6 +++++ 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h index 6c9c6a6e4ea..44610ed6de8 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h @@ -63,6 +63,13 @@ public: : Cb(c), circumcenter_(c.circumcenter_ != nullptr ? new Point(*(c.circumcenter_)) : nullptr) {} + Delaunay_triangulation_cell_base_with_circumcenter_3 + (Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) + : Cb(std::move(c)), circumcenter_(nullptr) + { + std::swap(circumcenter_, c.circumcenter_); + } + Delaunay_triangulation_cell_base_with_circumcenter_3& operator=(const Delaunay_triangulation_cell_base_with_circumcenter_3 &c) { @@ -71,6 +78,14 @@ public: return *this; } + Delaunay_triangulation_cell_base_with_circumcenter_3& + operator=(Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) + { + Delaunay_triangulation_cell_base_with_circumcenter_3 tmp=std::move(c); + std::swap(tmp, *this); + return *this; + } + Delaunay_triangulation_cell_base_with_circumcenter_3( Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 17cabad626a..3d56833e370 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -193,21 +193,42 @@ public: CGAL_triangulation_postcondition(is_valid()); } + Regular_triangulation_3(Regular_triangulation_3&& rt) + noexcept(noexcept(Tr_Base(std::move(rt)))) + : Tr_Base(std::move(rt)), hidden_point_visitor(this) + { + CGAL_triangulation_postcondition(is_valid()); + } + + ~Regular_triangulation_3() = default; + void swap(Regular_triangulation_3& tr) + noexcept(noexcept(this->Tr_Base::swap(tr))) { // The 'vertices' and 'hidden_points' members of 'hidden_point_visitor' should be empty // as they are only filled (and cleared) during the insertion of a point. // Hidden points are not stored there, but rather in cells. Thus, the only thing that must be set // is the triangulation pointer. Hidden_point_visitor new_hpv(this); - std::swap(hidden_point_visitor, new_hpv); + using std::swap; + swap(hidden_point_visitor, new_hpv); Tr_Base::swap(tr); } - Regular_triangulation_3& operator=(Regular_triangulation_3 tr) + Regular_triangulation_3& operator=(const Regular_triangulation_3& tr) { - swap(tr); + Regular_triangulation_3 copy(tr); + copy.swap(*this); + return *this; + } + + Regular_triangulation_3& operator=(Regular_triangulation_3&& tr) + noexcept(noexcept(Regular_triangulation_3(std::move(tr))) && + noexcept(std::declval().swap(*this))) + { + Regular_triangulation_3 copy(std::move(tr)); + copy.swap(*this); return *this; } diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 6941c6c8acf..07cc5761a31 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -728,6 +728,9 @@ public: CGAL_triangulation_expensive_postcondition(*this == tr); } + Triangulation_3(Triangulation_3&& tr) = default; + ~Triangulation_3() = default; + template < typename InputIterator > Triangulation_3(InputIterator first, InputIterator last, const GT& gt = GT(), Lock_data_structure *lock_ds = nullptr) @@ -754,21 +757,21 @@ public: init_tds(); } - Triangulation_3& operator=(Triangulation_3 tr) + Triangulation_3& operator=(const Triangulation_3& tr) { - // Because the parameter tr is passed by value, the triangulation passed - // as argument has been copied. - // The following 'swap' consumes the *copy* and the original triangulation - // is left untouched. - swap(tr); + Triangulation_3 copy(tr); + swap(copy); return *this; } + Triangulation_3& operator=(Triangulation_3&& tr) = default; + // HELPING FUNCTIONS - void swap(Triangulation_3& tr) + void swap(Triangulation_3& tr) noexcept { - std::swap(tr._gt, _gt); - std::swap(tr.infinite, infinite); + using std::swap; + swap(tr._gt, _gt); + swap(tr.infinite, infinite); _tds.swap(tr._tds); Base::swap(tr); } diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h index e2c9029eb10..a6b5ded18a7 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -170,6 +171,11 @@ _test_cls_delaunay_3(const Triangulation &) { typedef Triangulation Cls; + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Test_location_policy::Location_policy Location_policy; // We assume the traits class has been tested already diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h index 3c646b27be4..6c5793d0de2 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h @@ -15,12 +15,19 @@ #include #include #include +#include #include template void _test_cls_regular_3(const Triangulation &) { typedef Triangulation Cls; + + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Triangulation::Geom_traits Gt; CGAL_USE_TYPE(Gt); diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h index 3d647fcad94..b73de19db78 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "_test_cls_iterator.h" #include "_test_cls_circulator.h" @@ -79,6 +80,11 @@ _test_cls_triangulation_3(const Triangulation &) { typedef Triangulation Cls; + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // We assume the traits class has been tested already // actually, any traits is good if it has been tested