Merge pull request #7373 from sloriot/Kernel-Perfect_forwarding

Add some perfect forwarding in the Kernel
This commit is contained in:
Laurent Rineau 2024-05-15 16:12:23 +02:00
commit e9fb0190c3
42 changed files with 492 additions and 116 deletions

View File

@ -47,7 +47,7 @@ public:
DirectionC2() {}
DirectionC2(const FT &x, const FT &y)
: base(CGAL::make_array(x, y)) {}
: base{x, y} {}
bool operator==(const DirectionC2 &d) const;
bool operator!=(const DirectionC2 &d) const;

View File

@ -45,7 +45,7 @@ public:
DirectionC3() {}
explicit DirectionC3(const Vector_3 &v)
: base(CGAL::make_array(v.x(), v.y(), v.z())) {}
: base{v.x(), v.y(), v.z()} {}
// { *this = v.direction(); }
explicit DirectionC3(const Line_3 &l)
@ -58,7 +58,7 @@ public:
{ *this = s.rep().direction(); }
DirectionC3(const FT &x, const FT &y, const FT &z)
: base(CGAL::make_array(x, y, z)) {}
: base{x, y, z} {}
typename R::Boolean operator==(const DirectionC3 &d) const;
typename R::Boolean operator!=(const DirectionC3 &d) const;

View File

@ -43,7 +43,7 @@ public:
Iso_cuboidC3() {}
Iso_cuboidC3(const Point_3 &p, const Point_3 &q, int)
: base(CGAL::make_array(p, q))
: base{p, q}
{
// I have to remove the assertions, because of Cartesian_converter.
// CGAL_kernel_assertion(p.x()<=q.x());
@ -68,8 +68,8 @@ public:
Iso_cuboidC3(const Point_3 &left, const Point_3 &right,
const Point_3 &bottom, const Point_3 &top,
const Point_3 &far_, const Point_3 &close)
: base(CGAL::make_array(Construct_point_3()(left.x(), bottom.y(), far_.z()),
Construct_point_3()(right.x(), top.y(), close.z())))
: base{Construct_point_3()(left.x(), bottom.y(), far_.z()),
Construct_point_3()(right.x(), top.y(), close.z())}
{
CGAL_kernel_precondition(!less_x(right, left));
CGAL_kernel_precondition(!less_y(top, bottom));

View File

@ -43,7 +43,7 @@ public:
// : base(p, q) {}
Iso_rectangleC2(const Point_2 &p, const Point_2 &q, int)
: base(CGAL::make_array(p, q))
: base{p, q}
{
// I have to remove the assertions, because of Cartesian_converter.
// CGAL_kernel_assertion(p<=q);

View File

@ -46,7 +46,7 @@ public:
LineC2() {}
LineC2(const FT &a, const FT &b, const FT &c)
: base(CGAL::make_array(a, b, c)) {}
: base{a, b, c} {}
typename R_::Boolean operator==(const LineC2 &l) const;
typename R_::Boolean operator!=(const LineC2 &l) const;

View File

@ -64,7 +64,7 @@ public:
{ *this = plane_from_point_direction<R>(o, v.direction()); }
PlaneC3(const FT &a, const FT &b, const FT &c, const FT &d)
: base(CGAL::make_array(a, b, c, d)) {}
: base{a, b, c, d} {}
PlaneC3(const Line_3 &l, const Point_3 &p)
{ *this = plane_from_points<R>(l.point(),

View File

@ -44,11 +44,14 @@ public:
PointC2(const Origin &)
: base(NULL_VECTOR) {}
PointC2(const FT &x, const FT &y)
: base(x, y) {}
template <class T1, class T2>
PointC2(T1 &&x, T2 &&y)
: base(std::forward<T1>(x), std::forward<T2>(y))
{}
PointC2(const FT &hx, const FT &hy, const FT &hw)
: base(hx, hy, hw) {}
template <class T1, class T2, class T3>
PointC2(T1 &&hx, T2 &&hy, T3 &&hw)
: base(std::forward<T1>(hx), std::forward<T2>(hy), std::forward<T3>(hw)) {}
friend void swap(Self& a, Self& b)
#if !defined(__INTEL_COMPILER) && defined(__cpp_lib_is_swappable)

View File

@ -42,11 +42,17 @@ public:
PointC3(const Origin &)
: base(NULL_VECTOR) {}
PointC3(const FT &x, const FT &y, const FT &z)
: base(x, y, z) {}
PointC3(const FT &x, const FT &y, const FT &z, const FT &w)
: base(x, y, z, w) {}
template <class T1, class T2, class T3>
PointC3(T1 &&x, T2 &&y, T3 &&z)
: base(std::forward<T1>(x), std::forward<T2>(y), std::forward<T3>(z))
{}
template <class T1, class T2, class T3, class T4>
PointC3(T1 &&x, T2 &&y, T3 &&z, T4 &&w)
: base(std::forward<T1>(x), std::forward<T2>(y),
std::forward<T3>(z), std::forward<T4>(w))
{}
friend void swap(Self& a, Self& b)
#if !defined(__INTEL_COMPILER) && defined(__cpp_lib_is_swappable)

View File

@ -40,7 +40,7 @@ public:
{}
RayC2(const Point_2 &sp, const Point_2 &secondp)
: base(CGAL::make_array(sp, secondp))
: base{sp, secondp}
{}

View File

@ -43,16 +43,16 @@ public:
RayC3() {}
RayC3(const Point_3 &sp, const Point_3 &secondp)
: base(CGAL::make_array(sp, secondp)) {}
: base{sp, secondp} {}
RayC3(const Point_3 &sp, const Vector_3 &v)
: base(CGAL::make_array(sp, sp + v)) {}
: base{sp, sp + v} {}
RayC3(const Point_3 &sp, const Direction_3 &d)
: base(CGAL::make_array(sp, sp + d.to_vector())) {}
: base{sp, sp + d.to_vector()} {}
RayC3(const Point_3 &sp, const Line_3 &l)
: base(CGAL::make_array(sp, sp + l.to_vector())) {}
: base{sp, sp + l.to_vector()} {}
typename R::Boolean operator==(const RayC3 &r) const;
typename R::Boolean operator!=(const RayC3 &r) const;

View File

@ -39,7 +39,7 @@ public:
{}
SegmentC2(const Point_2 &sp, const Point_2 &ep)
: base(CGAL::make_array(sp, ep))
: base{sp, ep}
{}
const Point_2 &

View File

@ -42,7 +42,7 @@ public:
SegmentC3() {}
SegmentC3(const Point_3 &sp, const Point_3 &ep)
: base(CGAL::make_array(sp, ep)) {}
: base{sp, ep} {}
bool has_on(const Point_3 &p) const;
bool collinear_has_on(const Point_3 &p) const;

View File

@ -45,7 +45,7 @@ public:
TetrahedronC3(const Point_3 &p, const Point_3 &q, const Point_3 &r,
const Point_3 &s)
: base(CGAL::make_array(p, q, r, s)) {}
: base{p, q, r, s} {}
const Point_3 & vertex(int i) const;
const Point_3 & operator[](int i) const;

View File

@ -41,7 +41,7 @@ public:
TriangleC2() {}
TriangleC2(const Point_2 &p, const Point_2 &q, const Point_2 &r)
: base(CGAL::make_array(p, q, r)) {}
: base{p, q, r} {}
const Point_2 &

View File

@ -42,7 +42,7 @@ public:
TriangleC3() {}
TriangleC3(const Point_3 &p, const Point_3 &q, const Point_3 &r)
: base(CGAL::make_array(p, q, r)) {}
: base{p, q, r} {}
bool operator==(const TriangleC3 &t) const;
bool operator!=(const TriangleC3 &t) const;

View File

@ -50,7 +50,10 @@ public:
VectorC2() {}
VectorC2(const FT &x, const FT &y)
: base(CGAL::make_array(x, y)) {}
: base{x, y} {}
VectorC2(FT&& x, FT&& y)
: base{std::move(x), std::move(y)} {}
VectorC2(const FT &hx, const FT &hy, const FT &hw)
: base( hw != FT(1) ? CGAL::make_array<FT>(hx/hw, hy/hw)

View File

@ -65,7 +65,10 @@ public:
{ *this = R().construct_vector_3_object()(l); }
VectorC3(const FT_ &x, const FT_ &y, const FT_ &z)
: base(CGAL::make_array(x, y, z)) {}
: base{x, y, z} {}
VectorC3(FT_&& x, FT_&& y, FT_&& z)
: base{std::move(x), std::move(y), std::move(z)} {}
VectorC3(const FT_ &x, const FT_ &y, const FT_ &z, const FT_ &w)
: base( w != FT_(1) ? CGAL::make_array<FT_>(x/w, y/w, z/w)

View File

@ -3075,17 +3075,10 @@ namespace CartesianKernelFunctors {
typedef const Point_2& type;
};
template <typename ...Args>
Rep // Point_2
operator()(Return_base_tag, Origin o) const
{ return Rep(o); }
Rep // Point_2
operator()(Return_base_tag, const RT& x, const RT& y) const
{ return Rep(x, y); }
Rep // Point_2
operator()(Return_base_tag, const RT& x, const RT& y, const RT& w) const
{ return Rep(x, y, w); }
operator()(Return_base_tag, Args&& ...args) const
{ return Rep(std::forward<Args>(args)...); }
Point_2
operator()(const Line_2& l) const
@ -3097,7 +3090,7 @@ namespace CartesianKernelFunctors {
}
Point_2
operator()(const Line_2& l, const FT i) const
operator()(const Line_2& l, const FT& i) const
{
typename K::Construct_point_2 construct_point_2;
typename K::FT x, y;
@ -3121,6 +3114,10 @@ namespace CartesianKernelFunctors {
operator()(const RT& x, const RT& y) const
{ return Point_2(x, y); }
Point_2
operator()(RT&& x, RT&& y) const
{ return Point_2(std::move(x), std::move(y)); }
Point_2
operator()(const RT& x, const RT& y, const RT& w) const
{ return Point_2(x, y, w); }
@ -3151,18 +3148,10 @@ namespace CartesianKernelFunctors {
typedef const Point_3& type;
};
template <class ...Args>
Rep // Point_3
operator()(Return_base_tag, Origin o) const
{ return Rep(o); }
Rep // Point_3
operator()(Return_base_tag, const RT& x, const RT& y, const RT& z) const
{ return Rep(x, y, z); }
Rep // Point_3
operator()(Return_base_tag, const RT& x, const RT& y, const RT& z, const RT& w) const
{ return Rep(x, y, z, w); }
operator()(Return_base_tag, Args&& ...args) const
{ return Rep(std::forward<Args>(args)...); }
const Point_3&
operator()(const Point_3 & p) const
@ -3180,6 +3169,10 @@ namespace CartesianKernelFunctors {
operator()(const RT& x, const RT& y, const RT& z) const
{ return Point_3(x, y, z); }
Point_3
operator()(RT&& x, RT&& y, RT&& z) const
{ return Point_3(std::move(x), std::move(y), std::move(z)); }
Point_3
operator()(const RT& x, const RT& y, const RT& z, const RT& w) const
{ return Point_3(x, y, z, w); }
@ -3577,11 +3570,17 @@ namespace CartesianKernelFunctors {
operator()(Return_base_tag, const RT& x, const RT& y) const
{ return Rep(x, y); }
Rep
operator()(Return_base_tag, RT&& x, RT&& y) const
{ return Rep(std::move(x), std::move(y)); }
Rep // Vector_2
operator()(Return_base_tag, const RT& x, const RT& y, const RT& w) const
{ return Rep(x, y, w); }
Rep
operator()(Return_base_tag, RT&& x, RT&& y, RT&& w) const
{ return Rep(std::move(x), std::move(y), std::move(w)); }
Vector_2
operator()( const Point_2& p, const Point_2& q) const
@ -3681,6 +3680,10 @@ namespace CartesianKernelFunctors {
operator()(Return_base_tag, const RT& x, const RT& y, const RT& z) const
{ return Rep(x, y, z); }
Rep // Vector_3
operator()(Return_base_tag, RT&& x, RT&& y, RT&& z) const
{ return Rep(std::move(x), std::move(y), std::move(z)); }
Rep // Vector_3
operator()(Return_base_tag, const RT& x, const RT& y, const RT& z, const RT& w) const
{ return Rep(x, y, z, w); }

View File

@ -56,7 +56,7 @@ public:
DirectionH2() {}
DirectionH2(const RT& x, const RT& y)
: base(CGAL::make_array(x, y, RT(1))) {}
: base{x, y, RT(1)} {}
// TODO Not documented : should not exist, not used.
// we should also change array<RT, 3> -> array<RT, 2>

View File

@ -43,7 +43,7 @@ public:
Iso_cuboidH3() {}
Iso_cuboidH3(const Point_3& p, const Point_3& q, int)
: base(CGAL::make_array(p, q))
: base{p, q}
{
CGAL_kernel_assertion(p.x()<=q.x());
CGAL_kernel_assertion(p.y()<=q.y());
@ -173,8 +173,8 @@ CGAL_KERNEL_LARGE_INLINE
Iso_cuboidH3<R>::
Iso_cuboidH3(const RT& min_hx, const RT& min_hy, const RT& min_hz,
const RT& max_hx, const RT& max_hy, const RT& max_hz)
: base(CGAL::make_array(Point_3(min_hx, min_hy, min_hz, RT(1)),
Point_3(max_hx, max_hy, max_hz, RT(1))))
: base{Point_3(min_hx, min_hy, min_hz, RT(1)),
Point_3(max_hx, max_hy, max_hz, RT(1))}
{}
template < class R >

View File

@ -42,7 +42,7 @@ public:
Iso_rectangleH2() {}
Iso_rectangleH2(const Point_2& p, const Point_2& q, int)
: base(CGAL::make_array(p, q))
: base{p, q}
{
// I have to remove the assertions, because of Homogeneous_converter.
// CGAL_kernel_assertion(p.x()<=q.x());

View File

@ -45,7 +45,7 @@ public:
LineH2() {}
LineH2(const RT& a, const RT& b, const RT& c)
: base(CGAL::make_array(a, b, c)) {}
: base{a, b, c} {}
bool operator==(const LineH2<R>& l) const;
bool operator!=(const LineH2<R>& l) const;

View File

@ -63,7 +63,7 @@ public:
{ *this = R().construct_vector_3_object()(l); }
VectorH3(const Null_vector&)
: base(CGAL::make_array(RT(0), RT(0), RT(0), RT(1))) {}
: base{RT(0), RT(0), RT(0), RT(1)} {}
template < typename Tx, typename Ty, typename Tz >
VectorH3(const Tx & x, const Ty & y, const Tz & z,

View File

@ -29,8 +29,15 @@
namespace CGAL {
constexpr bool epeck_use_static_filter =
#ifdef CGAL_NO_STATIC_FILTERS
false;
#else
true;
#endif
// Epeck_ft is either Gmpq, or leda_rational, or Quotient<MP_float>
typedef internal::Exact_field_selector<double>::Type Epeck_ft;
using Epeck_ft = internal::Exact_field_selector<double>::Type;
// The following are redefined kernels instead of simple typedefs in order to shorten
// template name length (for error messages, mangling...).
@ -41,33 +48,36 @@ typedef internal::Exact_field_selector<double>::Type Epeck_ft;
class Epeck
: public Filtered_kernel_adaptor<
Type_equality_wrapper< Simple_cartesian<Lazy_exact_nt<Epeck_ft> >::Base<Epeck>::Type, Epeck >,
#ifdef CGAL_NO_STATIC_FILTERS
false >
#else
true >
#endif
epeck_use_static_filter >
{}; // end class Epeck
#else // no CGAL_DONT_USE_LAZY_KERNEL
namespace internal {
template <typename FT>
using Epeck_sc = Simple_cartesian<FT>;
using Epeck_interval = Simple_cartesian<Interval_nt_advanced>;
template <typename FT>
using Epeck_converter = Cartesian_converter<Epeck_sc<FT>, Epeck_interval>;
template <typename FT, typename Kernel>
using Epeck_lazy_base = Lazy_kernel_base<Epeck_sc<FT>, Epeck_interval, Epeck_converter<FT>, Kernel>;
template <typename FT, typename Kernel>
using Epeck_lazy_base_with_type_equality = Type_equality_wrapper<Epeck_lazy_base<FT, Kernel>, Kernel>;
} // namespace internal
// Equivalent to Lazy_kernel<Simple_cartesian<Epeck_ft> >
class Epeck
: public Type_equality_wrapper<
Lazy_kernel_base< Simple_cartesian<Epeck_ft>,
Simple_cartesian<Interval_nt_advanced>,
Cartesian_converter< Simple_cartesian<Epeck_ft>,
Simple_cartesian<Interval_nt_advanced> >,
Epeck>,
Epeck >
{};
class Epeck : public internal::Epeck_lazy_base_with_type_equality<Epeck_ft, Epeck> {};
#endif // no CGAL_DONT_USE_LAZY_KERNEL
typedef Epeck Exact_predicates_exact_constructions_kernel;
using Exact_predicates_exact_constructions_kernel = Epeck;
template <>
struct Triangulation_structural_filtering_traits<Epeck> {
typedef Tag_true Use_structural_filtering_tag;
using Use_structural_filtering_tag = Tag_true;
};
} //namespace CGAL

View File

@ -79,9 +79,11 @@ public:
: Rep(wp.point())
{}
template < typename T1, typename T2 >
Point_2(const T1 &x, const T2 &y)
: Rep(typename R::Construct_point_2()(Return_base_tag(), x, y))
template < typename T1, typename T2>
Point_2(T1&& x, T2&& y)
: Rep(typename R::Construct_point_2()(Return_base_tag(),
std::forward<T1>(x),
std::forward<T2>(y)))
{}
Point_2(const RT& hx, const RT& hy, const RT& hw)
@ -255,7 +257,7 @@ extract(std::istream& is, Point_2<R>& p, const Cartesian_tag&)
break;
}
if (is)
p = Point_2<R>(x, y);
p = Point_2<R>(std::move(x), std::move(y));
return is;
}

View File

@ -75,8 +75,10 @@ public:
{}
template < typename T1, typename T2, typename T3 >
Point_3(const T1& x, const T2& y, const T3& z)
: Rep(typename R::Construct_point_3()(Return_base_tag(), x, y, z))
Point_3(T1&& x, T2&& y, T3&& z)
: Rep(typename R::Construct_point_3()(Return_base_tag(), std::forward<T1>(x),
std::forward<T2>(y),
std::forward<T3>(z)))
{}
Point_3(const RT& hx, const RT& hy, const RT& hz, const RT& hw)
@ -283,7 +285,7 @@ extract(std::istream& is, Point_3<R>& p, const Cartesian_tag&)
break;
}
if (is)
p = Point_3<R>(x, y, z);
p = Point_3<R>(std::move(x), std::move(y), std::move(z));
return is;
}

View File

@ -88,8 +88,11 @@ public:
: RVector_2(typename R::Construct_vector_2()(Return_base_tag(), v)) {}
template < typename T1, typename T2 >
Vector_2(const T1 &x, const T2 &y)
: RVector_2(typename R::Construct_vector_2()(Return_base_tag(), x,y)) {}
Vector_2(T1&& x, T2&& y)
: RVector_2(typename R::Construct_vector_2()(Return_base_tag(),
std::forward<T1>(x),
std::forward<T2>(y)))
{}
Vector_2(const RT &x, const RT &y, const RT &w)
: RVector_2(typename R::Construct_vector_2()(Return_base_tag(), x,y,w)) {}

View File

@ -88,8 +88,11 @@ public:
: Rep(typename R::Construct_vector_3()(Return_base_tag(), v)) {}
template < typename T1, typename T2, typename T3 >
Vector_3(const T1 &x, const T2 &y, const T3 &z)
: Rep(typename R::Construct_vector_3()(Return_base_tag(), x, y, z)) {}
Vector_3(T1&& x, T2&& y, T3&& z)
: Rep(typename R::Construct_vector_3()(Return_base_tag(), std::forward<T1>(x),
std::forward<T2>(y),
std::forward<T3>(z)))
{}
Vector_3(const RT& x, const RT& y, const RT& z, const RT& w)
: Rep(typename R::Construct_vector_3()(Return_base_tag(), x, y, z, w)) {}

View File

@ -25,8 +25,14 @@
// The following is needed for LEDA 4.4 due to min/max problems...
# define LEDA_NO_MIN_MAX_TEMPL
#ifdef CGAL_CXX20
# define STREAM_DUMMY // disable stream_dummy() function that is not used and using features removed from c++20
// We cannot undef STREAM_DUMMY as LEDA/internal/PREAMBULE.h is not protected
#endif
#include <LEDA/system/basic.h>
#ifdef LEDA_NAMESPACE
# define CGAL_LEDA_SCOPE leda
#else

View File

@ -23,6 +23,7 @@
#include <vector>
#include <math.h>
#include <cmath>
#include <cstdint>
#include <iostream>
#include <stdexcept>
#ifdef CGAL_USE_GMPXX

View File

@ -0,0 +1,187 @@
// Copyright (c) 2024, GeometryFactory Sarl (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s) : Laurent Rineau
#ifndef CGAL_NT_WRAPPER_H
#define CGAL_NT_WRAPPER_H
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Coercion_traits.h>
#include <CGAL/Real_embeddable_traits.h>
#include <CGAL/Kernel/global_functions.h>
#include <CGAL/Kernel/Type_equality_wrapper.h>
#include <CGAL/functional.h>
#include <functional>
#include <source_location>
namespace CGAL {
/*
* This class template `NT_wapper<NT>` is currently undocumented, on purpose.
*
* This class template provides a wrapper for number types. It calls a function
* `f` when a constructor, destructor, or assignment operator is called. This
* is useful to detect when a copy constructor is called, for example. An
* example of use case is in the test file
* `Number_types/test/Number_types/wrapping_type.cpp`.
*/
template <typename NT>
class NT_wrapper {
NT value;
static void call_f(const std::source_location& l = std::source_location::current()) {
if (f)
f(l);
}
public:
inline static std::function<void(const std::source_location&)> f;
NT_wrapper() : value(0) { call_f(std::source_location::current()); }
NT_wrapper(const NT& val) : value(val) { call_f(std::source_location::current());}
NT_wrapper(NT&& val) : value(std::move(val)) { call_f(std::source_location::current()); }
NT_wrapper(int val) : value(val) { call_f(std::source_location::current()); }
template <typename T, typename = std::enable_if_t<!std::is_same_v<T, NT>>>
NT_wrapper(const NT_wrapper<T>& other) : value(other.get_value()) { call_f(std::source_location::current()); }
NT_wrapper(const NT_wrapper& other) : value(other.value) { call_f(std::source_location::current()); }
NT_wrapper(NT_wrapper&& other) : value(std::move(other.value)) { call_f(std::source_location::current()); }
~NT_wrapper() { call_f(std::source_location::current()); }
NT_wrapper& operator=(const NT_wrapper& other) {
if (this != &other) {
value = other.value;
call_f(std::source_location::current());
}
return *this;
}
NT_wrapper& operator=(NT_wrapper&& other) {
if (this != &other) {
value = std::move(other.value);
call_f(std::source_location::current());
}
return *this;
}
NT get_value() const {
return value;
}
operator NT() const {
return value;
}
NT_wrapper operator+(const NT_wrapper& rhs) const {
return NT_wrapper(value + rhs.value);
}
NT_wrapper operator-(const NT_wrapper& rhs) const {
return NT_wrapper(value - rhs.value);
}
NT_wrapper operator*(const NT_wrapper& rhs) const {
return NT_wrapper(value * rhs.value);
}
NT_wrapper operator/(const NT_wrapper& rhs) const {
return NT_wrapper(value / rhs.value);
}
NT_wrapper operator/(int rhs) const {
return NT_wrapper(value / rhs);
}
bool operator==(const NT_wrapper& rhs) const {
return value == rhs.value;
}
bool operator!=(const NT_wrapper& rhs) const {
return value != rhs.value;
}
bool operator<(const NT_wrapper& rhs) const {
return value < rhs.value;
}
bool operator>(const NT_wrapper& rhs) const {
return value > rhs.value;
}
bool operator<=(const NT_wrapper& rhs) const {
return value <= rhs.value;
}
bool operator>=(const NT_wrapper& rhs) const {
return value >= rhs.value;
}
};
CGAL_DEFINE_COERCION_TRAITS_FROM_TO_TEM(NT_wrapper<NT>, double, typename NT)
template <typename NT>
struct Real_embeddable_traits<NT_wrapper<NT>>
: public INTERN_RET::Real_embeddable_traits_base<NT_wrapper<NT>,
typename Real_embeddable_traits<NT>::Is_real_embeddable>
{
using Type = NT_wrapper<NT>;
class Sgn
: public CGAL::cpp98::unary_function< NT, ::CGAL::Sign > {
public:
::CGAL::Sign operator()( const Type& x ) const {
return CGAL_NTS sign( x.get_value() );
}
};
class To_double
: public CGAL::cpp98::unary_function< NT, double > {
public:
double operator()( const Type& x) const {
return CGAL_NTS to_double( x.get_value() );
}
};
class To_interval
: public CGAL::cpp98::unary_function< NT, std::pair<double,double> > {
public:
std::pair<double,double> operator()( const Type& x ) const {
return CGAL_NTS to_interval( x.get_value() );
}
};
};
namespace internal {
template <typename T>
struct Exact_field_selector<NT_wrapper<T>> {
using Type = NT_wrapper<typename Exact_field_selector<T>::Type>;
using type = Type;
};
template <typename T>
struct Exact_ring_selector<NT_wrapper<T>> {
using Type = NT_wrapper<typename Exact_ring_selector<T>::Type>;
using type = Type;
};
} // namespace internal
struct Wrapped_epick
: public CGAL::internal::Epick_with_filtered_predicates<NT_wrapper<double>, Wrapped_epick>
{};
struct Wrapped_epeck
: public CGAL::internal::Epeck_lazy_base_with_type_equality<NT_wrapper<CGAL::Epeck_ft>, Wrapped_epeck>
{};
} // namespace CGAL
#endif // CGAL_NT_WRAPPER_H

View File

@ -24,11 +24,12 @@
#define CGAL_KNOWN_BIT_SIZE_INTEGERS_H
#define CGAL_DEPRECATED_HEADER "<CGAL/known_bit_size_integers.h>"
#define CGAL_REPLACEMENT_HEADER "<boost/cstdint.hpp>"
#define CGAL_REPLACEMENT_HEADER "<cstdint>"
#include <CGAL/Installation/internal/deprecation_warning.h>
#include <CGAL/number_type_basic.h>
#include <boost/cstdint.hpp>
#include <cstdint>
#ifndef CGAL_NO_DEPRECATED_CODE

View File

@ -62,6 +62,7 @@ create_single_source_cgal_program("utilities.cpp")
create_single_source_cgal_program("Exact_rational.cpp")
create_single_source_cgal_program("Mpzf_new.cpp")
create_single_source_cgal_program("check_exact_backend.cpp")
create_single_source_cgal_program("wrapping_type.cpp" CXX_FEATURES cxx_std_20)
if( CGAL_Core_FOUND )
create_single_source_cgal_program( "CORE_Expr_ticket_4296.cpp" )

View File

@ -1,10 +1,10 @@
#include <iostream>
#include <boost/cstdint.hpp>
#include <cstdint>
#include <CGAL/assertions.h>
int main()
{
std::cout << "Verifying the sizes of boost::[u]int{8,16,32,64}_t"
std::cout << "Verifying the sizes of std::[u]int{8,16,32,64}_t"
<< std::endl;
static_assert(sizeof(std::int8_t) == 1);

View File

@ -0,0 +1,53 @@
#include <iostream>
#include <map>
#include <CGAL/config.h>
#if __has_include(<source_location>)
#include <CGAL/NT_wrapper.h>
struct Map {
std::map<std::string, std::size_t> m;
void increment(const std::string& key) {
m[key]++;
}
~Map() {
for(const auto& [key, value] : m)
std::clog << value << " " << key << std::endl;
}
} map;
void incr_counter(const std::source_location& l) {
map.increment(l.function_name());
}
using K = CGAL::Wrapped_epick;
using EK = CGAL::Wrapped_epeck;
int main() {
CGAL::NT_wrapper<double>::f = incr_counter;
CGAL::NT_wrapper<CGAL::Epeck_ft>::f = incr_counter;
K ::Point_2 p1(0, 2), p2(2, 4), p3(4, 6);
EK::Point_2 p4(0, 2), p5(2, 4), p6(4, 6);
exact(p4);
exact(p5);
exact(p6);
[[maybe_unused]] bool result_2d_k = CGAL::orientation(p1, p2, p3) == CGAL::COLLINEAR;
[[maybe_unused]] bool result_2d_e = CGAL::orientation(p4, p5, p6) == CGAL::COLLINEAR;
assert (result_2d_k && result_2d_e);
for(auto [key, _] : map.m) {
if(key.find("const") != std::string::npos) {
std::cerr << "ERROR: copy constructor called!\n";
return 1;
}
}
return 0;
}
#else
int main() {
std::cerr << "C++20 <source_location> not available\n";
return 0;
}
#endif

View File

@ -6,8 +6,6 @@ namespace CGAL {
\returns `std::array<T, N>` where `N` is the number of arguments given to
the function. The position of each argument in the array is the same
as its position in the argument list.
The maximal number of arguments is `6`.
*/
template <class T> std::array<T, N> make_array(const T&...);
@ -18,8 +16,6 @@ arguments given to the function. The position of each argument in the
array is the same as its position in the argument list.
This is the functor version of `make_array()`.
The maximal number of arguments is `6`.
*/
struct Construct_array
{

View File

@ -42,7 +42,7 @@ class Handle_for
T t;
std::atomic_uint count;
template <class... U>
RefCounted(U&&...u ) : t(std::forward<U>(u)...), count(1) {}
RefCounted(U&&...u ) : t{std::forward<U>(u)...}, count(1) {}
};

View File

@ -13,6 +13,7 @@
#define CGAL_ARRAY_H
#include <CGAL/config.h>
#include <CGAL/type_traits.h>
#include <array>
#include <utility>
@ -45,25 +46,48 @@ namespace CGAL {
// It's also untrue that this is not documented... It is !
template< typename T, typename... Args >
BOOST_CXX14_CONSTEXPR
std::array< T, 1 + sizeof...(Args) >
make_array(const T & t, const Args & ... args)
{
std::array< T, 1 + sizeof...(Args) > a = { { t, static_cast<T>(args)... } };
return a;
}
template <typename T, typename ...Args>
struct Make_array_element_type {
using type = T;
};
template <typename ...Args>
struct Make_array_element_type<void, Args...> {
using type = typename std::common_type_t<Args...>;
};
template <typename T, typename ...Args>
using Make_array_element_type_t = typename Make_array_element_type<T, Args...>::type;
template<typename T = void, typename... Args>
constexpr
std::array<Make_array_element_type_t<T, Args...>, sizeof...(Args) >
make_array(Args&& ... args)
{
using Target_type = Make_array_element_type_t<T, Args...>;
// MSVC 2017 chokes on the following code, so we simplify it for this compiler
// See https://godbolt.org/z/7Y34Y1c53
#if ! defined(_MSC_VER) || (_MSC_VER > 1916)
if constexpr ( (CGAL::is_convertible_without_narrowing_v<cpp20::remove_cvref_t<Args>, Target_type>&&...) )
return {{ std::forward<Args>(args)... }};
else
#endif // not MSVC or MSVC 2019 or later
{
std::array< Target_type, sizeof...(Args) > a = { { static_cast<Target_type>(args)... } };
return a;
}
}
// Functor version
struct Construct_array
{
template <typename T, typename... Args>
template <typename... Args>
constexpr
std::array<T, 1 + sizeof...(Args)>
operator()(const T& t, const Args& ... args) const
decltype(auto)
operator()(Args&& ... args) const
{
return make_array (t, args...);
return make_array( std::forward<Args>(args)... );
}
};

View File

@ -29,6 +29,12 @@ struct is_same_or_derived :
namespace cpp20 {
template<class T>
struct type_identity { using type = T; };
template<class T>
using type_identity_t = typename type_identity<T>::type;
template< class T >
struct remove_cvref {
typedef std::remove_cv_t<std::remove_reference_t<T>> type;
@ -39,6 +45,26 @@ namespace cpp20 {
} // end namespace cpp20
namespace details {
template <typename From, typename To, typename = void>
struct is_convertible_without_narrowing : std::false_type
{};
template <typename From, typename To>
struct is_convertible_without_narrowing<From,
To,
std::void_t<decltype(cpp20::type_identity_t<To[]>{std::declval<From>()})>>
: std::is_convertible<From, To>
{};
}
template <typename From, typename To>
struct is_convertible_without_narrowing : details::is_convertible_without_narrowing<From, To>
{};
template <typename From, typename To>
inline constexpr bool is_convertible_without_narrowing_v = is_convertible_without_narrowing<From, To>::value;
} // end namespace CGAL
#endif // CGAL_TYPE_TRAITS_H

View File

@ -53,6 +53,8 @@ create_single_source_cgal_program("test_for_each.cpp")
create_single_source_cgal_program("test_skiplist.cpp")
create_single_source_cgal_program("test_leak.cpp")
create_single_source_cgal_program("test_nth_element.cpp")
create_single_source_cgal_program("test_fwd_make_array.cpp")
if(TARGET CGAL::TBB_support)
message(STATUS "Found TBB")
target_link_libraries(test_for_each PUBLIC CGAL::TBB_support)

View File

@ -0,0 +1,33 @@
#include <iostream>
#include <CGAL/array.h>
#include <CGAL/use.h>
struct B {};
struct A // move-only class, move-constructible from B
{
A(B&&) {}
A(const A&) = delete;
A(A&&) = default;
};
int main()
{
#if ! defined(_MSC_VER) || (_MSC_VER > 1916)
// This test requires C++17 mandatory return-value optimization (RVO).
//
// MSVC-2017 does not implement C++17 correctly
// See https://godbolt.org/z/7Y34Y1c53
// and commit 15349f0bdafe60b85697f9d142c2652200d968e8
// where we introduced a workaround for MSVC-2017: disable the correct
// forwarding of arguments in the `make_array` function.
// For that reason we disable this test for MSVC-2017)
std::array<A, 1> a = CGAL::make_array<A>(B());
CGAL_USE(a);
#endif
auto b = CGAL::make_array<double>(1u);
static_assert(std::is_same_v<decltype(b), std::array<double, 1>>);
CGAL_USE(b);
return 0;
}

View File

@ -18,14 +18,22 @@ struct B : public A {};
typedef A C;
int main() {
assert( ( ::CGAL::is_same_or_derived< A,A >::value == 1 ) );
assert( ( ::CGAL::is_same_or_derived< A,B >::value == 1 ) );
assert( ( ::CGAL::is_same_or_derived< B,A >::value == 0 ) );
assert( ( ::CGAL::is_same_or_derived< B,B >::value == 1 ) );
assert( ( ::CGAL::is_same_or_derived< A,C >::value == 1 ) );
assert( ( ::CGAL::is_same_or_derived< B,C >::value == 0 ) );
assert( ( ::CGAL::is_same_or_derived< C,C >::value == 1 ) );
assert( ( ::CGAL::is_same_or_derived< C,A >::value == 1 ) );
assert( ( ::CGAL::is_same_or_derived< C,B >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< A,A >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< A,B >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< B,A >::value == 0 ) );
static_assert( ( ::CGAL::is_same_or_derived< B,B >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< A,C >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< B,C >::value == 0 ) );
static_assert( ( ::CGAL::is_same_or_derived< C,C >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< C,A >::value == 1 ) );
static_assert( ( ::CGAL::is_same_or_derived< C,B >::value == 1 ) );
static_assert( CGAL::is_convertible_without_narrowing_v<int, int> );
static_assert( ! CGAL::is_convertible_without_narrowing_v<int, signed char> );
static_assert( CGAL::is_convertible_without_narrowing_v<signed char, int> );
static_assert( ! CGAL::is_convertible_without_narrowing_v<int, double> );
static_assert( CGAL::is_convertible_without_narrowing_v<float, double> );
static_assert( ! CGAL::is_convertible_without_narrowing_v<double, float> );
static_assert( ! CGAL::is_convertible_without_narrowing_v<A, int> );
return 0;
}