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.
This commit is contained in:
Laurent Rineau 2020-01-31 11:23:37 +01:00
parent 3b564a20f8
commit b56cdcb743
6 changed files with 70 additions and 12 deletions

View File

@ -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)

View File

@ -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<Concurrency_tag> 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<Regular_triangulation_3>().swap(*this)))
{
Regular_triangulation_3 copy(std::move(tr));
copy.swap(*this);
return *this;
}

View File

@ -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);
}

View File

@ -19,6 +19,7 @@
#include <fstream>
#include <list>
#include <vector>
#include <type_traits>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/if.hpp>
@ -170,6 +171,11 @@ _test_cls_delaunay_3(const Triangulation &)
{
typedef Triangulation Cls;
static_assert(std::is_nothrow_move_constructible<Cls>::value,
"move cstr is missing");
static_assert(std::is_nothrow_move_assignable<Cls>::value,
"move assignment is missing");
typedef typename Test_location_policy<Cls>::Location_policy Location_policy;
// We assume the traits class has been tested already

View File

@ -15,12 +15,19 @@
#include <iostream>
#include <fstream>
#include <list>
#include <type_traits>
#include <CGAL/use.h>
template <class Triangulation>
void
_test_cls_regular_3(const Triangulation &)
{
typedef Triangulation Cls;
static_assert(std::is_nothrow_move_constructible<Cls>::value,
"move cstr is missing");
static_assert(std::is_nothrow_move_assignable<Cls>::value,
"move assignment is missing");
typedef typename Triangulation::Geom_traits Gt;
CGAL_USE_TYPE(Gt);

View File

@ -15,6 +15,7 @@
#include <fstream>
#include <list>
#include <vector>
#include <type_traits>
#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<Cls>::value,
"move cstr is missing");
static_assert(std::is_nothrow_move_assignable<Cls>::value,
"move assignment is missing");
// We assume the traits class has been tested already
// actually, any traits is good if it has been tested