Revert back to wrapping result_type to distinguish FT-necessary operator()s

This commit is contained in:
Mael Rouxel-Labbé 2022-10-12 21:24:59 +02:00
parent 9d40a225ff
commit 2c23a6d5c5
5 changed files with 71 additions and 74 deletions

View File

@ -445,20 +445,16 @@ namespace CartesianKernelFunctors {
return cmp_dist_to_pointC2(p.x(), p.y(), q.x(), q.y(), r.x(), r.y());
}
// Slightly wkward, but not to get a false positive in the `test_RT_or_FT_predicate`
// as otherwise trying to compile P2,P2,P2,FT_necessary would match the T1,T2,T3 templated operator()
result_type operator()(const Point_2& p, const Point_2& q, const Point_2& r, FT_necessary) = delete;
template <class T1, class T2, class T3>
result_type
operator()(const T1& p, const T2& q, const T3& r, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const T3& r) const
{
return CGAL::compare(squared_distance(p, q), squared_distance(p, r));
}
template <class T1, class T2, class T3, class T4>
std::enable_if_t<!std::is_same<T4, FT_necessary>::value, result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s) const
{
return CGAL::compare(squared_distance(p, q), squared_distance(r, s));
}
@ -596,15 +592,15 @@ namespace CartesianKernelFunctors {
}
template <class T1, class T2, class T3>
result_type
operator()(const T1& p, const T2& q, const T3& r, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const T3& r) const
{
return CGAL::compare(squared_distance(p, q), squared_distance(p, r));
}
template <class T1, class T2, class T3, class T4>
std::enable_if_t<!std::is_same<T4, FT_necessary>::value, result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s) const
{
return CGAL::compare(squared_distance(p, q), squared_distance(r, s));
}
@ -3981,8 +3977,8 @@ namespace CartesianKernelFunctors {
operator()(const Circle_3 &a, const Point_3 &p) const
{ return a.rep().has_on(p); }
result_type
operator()(const Sphere_3 &a, const Circle_3 &p, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const Sphere_3 &a, const Circle_3 &p) const
{ return a.rep().has_on(p); }
result_type

View File

@ -86,15 +86,8 @@ public:
template <typename... Args>
result_type
operator()(const Args&... args) const;
};
template <class EP, class AP, class C2E, class C2A, bool Protection>
template <typename... Args>
typename Filtered_predicate<EP,AP,C2E,C2A,Protection>::result_type
Filtered_predicate<EP,AP,C2E,C2A,Protection>::
operator()(const Args&... args) const
{
{
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
// Protection is outside the try block as VC8 has the CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG
{
@ -111,7 +104,8 @@ Filtered_predicate<EP,AP,C2E,C2A,Protection>::
Protect_FPU_rounding<!Protection> p(CGAL_FE_TONEAREST);
CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_TONEAREST);
return ep(c2e(args)...);
}
}
};
template <class EP_RT, class EP_FT, class AP, class C2E_RT, class C2E_FT, class C2A, bool Protection = true>
class Filtered_predicate_RT_FT
@ -123,27 +117,17 @@ class Filtered_predicate_RT_FT
EP_FT ep_ft;
AP ap;
using Ares = typename AP::result_type;
using Ares = typename Remove_needs_FT<typename AP::result_type>::Type;
public:
using result_type = typename EP_FT::result_type;
using result_type = typename Remove_needs_FT<typename EP_FT::result_type>::Type;
template <typename... Args>
struct Call_operator_needs_FT
{
// This type traits class checks if the call operator can be called with
// `(const Args&..., FT_necessary())`.
using ArrayOfOne = char[1];
using ArrayOfTwo = char[2];
static ArrayOfOne& test(...);
template <typename... Args2>
static auto test(const Args2 &...args)
-> decltype(ap(c2a(args)..., FT_necessary()),
std::declval<ArrayOfTwo &>());
enum { value = sizeof(test(std::declval<const Args&>()...)) == sizeof(ArrayOfTwo) };
using Actual_approx_res = decltype(ap(c2a(std::declval<const Args&>())...));
using Approx_res = std::remove_cv_t<std::remove_reference_t<Actual_approx_res> >;
enum { value = std::is_same<Approx_res, Needs_FT<Ares> >::value };
};
// ## Important note
@ -154,9 +138,7 @@ public:
// or `has_needs_FT<typename R::Compare_distance_3>` in
// the file `Kernel_23/test/Kernel_23/include/CGAL/_test_new_3.h`.
template <typename... Args>
constexpr bool needs_FT(const Args&...) const {
return Call_operator_needs_FT<Args...>::value;
}
bool needs_FT(const Args&...) const { return Call_operator_needs_FT<Args...>::value; }
template <typename... Args>
result_type

View File

@ -737,12 +737,12 @@ namespace CommonKernelFunctors {
typedef Comparison_result result_type;
result_type operator()(const Weighted_point_3 & p,
const Weighted_point_3 & q,
const Weighted_point_3 & r,
const Weighted_point_3 & s,
const FT& w,
FT_necessary = {}) const
Needs_FT<result_type>
operator()(const Weighted_point_3 & p,
const Weighted_point_3 & q,
const Weighted_point_3 & r,
const Weighted_point_3 & s,
const FT& w) const
{
return CGAL::compare(squared_radius_orthogonal_sphereC3(
p.x(),p.y(),p.z(),p.weight(),
@ -752,11 +752,11 @@ namespace CommonKernelFunctors {
w);
}
result_type operator()(const Weighted_point_3 & p,
const Weighted_point_3 & q,
const Weighted_point_3 & r,
const FT& w,
FT_necessary = {}) const
Needs_FT<result_type>
operator()(const Weighted_point_3 & p,
const Weighted_point_3 & q,
const Weighted_point_3 & r,
const FT& w) const
{
return CGAL::compare(squared_radius_smallest_orthogonal_sphereC3(
p.x(),p.y(),p.z(),p.weight(),
@ -765,10 +765,10 @@ namespace CommonKernelFunctors {
w);
}
result_type operator()(const Weighted_point_3 & p,
const Weighted_point_3 & q,
const FT& w,
FT_necessary = {}) const
Needs_FT<result_type>
operator()(const Weighted_point_3 & p,
const Weighted_point_3 & q,
const FT& w) const
{
return CGAL::compare(squared_radius_smallest_orthogonal_sphereC3(
p.x(),p.y(),p.z(),p.weight(),
@ -821,15 +821,15 @@ namespace CommonKernelFunctors {
typedef typename K::Comparison_result result_type;
template <class T1, class T2>
result_type
operator()(const T1& p, const T2& q, const FT& d2, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const FT& d2) const
{
return CGAL::compare(internal::squared_distance(p, q, K()), d2);
}
template <class T1, class T2, class T3, class T4>
std::enable_if_t<!std::is_same<T4, FT_necessary>::value, result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s) const
{
return CGAL::compare(internal::squared_distance(p, q, K()),
internal::squared_distance(r, s, K()));
@ -844,15 +844,15 @@ namespace CommonKernelFunctors {
typedef typename K::Comparison_result result_type;
template <class T1, class T2>
result_type
operator()(const T1& p, const T2& q, const FT& d2, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const FT& d2) const
{
return CGAL::compare(internal::squared_distance(p, q, K()), d2);
}
template <class T1, class T2, class T3, class T4>
std::enable_if_t<!std::is_same<T4, FT_necessary>::value, result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s, FT_necessary = {}) const
Needs_FT<result_type>
operator()(const T1& p, const T2& q, const T3& r, const T4& s) const
{
return CGAL::compare(internal::squared_distance(p, q, K()),
internal::squared_distance(r, s, K()));
@ -3024,10 +3024,11 @@ namespace CommonKernelFunctors {
public:
typedef typename K::Boolean result_type;
// Needs FT because Line/Line (and variations) and Circle_2/X compute intersections
template <class T1, class T2>
result_type
operator()(const T1& t1, const T2& t2, FT_necessary = {}) const
{ return Intersections::internal::do_intersect(t1, t2, K()); }
Needs_FT<result_type>
operator()(const T1& t1, const T2& t2) const
{ return { Intersections::internal::do_intersect(t1, t2, K())}; }
};
template <typename K>
@ -3337,9 +3338,9 @@ namespace CommonKernelFunctors {
}
// returns true iff the line segment ab is inside the union of the bounded sides of s1 and s2.
result_type operator()(const Sphere_3& s1, const Sphere_3& s2,
const Point_3& a, const Point_3& b,
FT_necessary = {}) const
Needs_FT<result_type>
operator()(const Sphere_3& s1, const Sphere_3& s2,
const Point_3& a, const Point_3& b) const
{
typedef typename K::Circle_3 Circle_3;
typedef typename K::Point_3 Point_3;

View File

@ -15,7 +15,7 @@
// Author(s) : Sylvain Pion
// This defines removes the operator/ from CGAL::Mpzf to check that functors not using
// the tag `FT_necessary` really only need a RT (ring type) without division.
// the tag `Needs_FT<>` really only need a RT (ring type) without division.
#define CGAL_NO_MPZF_DIVISION_OPERATOR 1
#include <CGAL/Cartesian.h>

View File

@ -81,9 +81,27 @@ Assert_compile_time_tag( const Tag&, const Derived& b)
x.match_compile_time_tag(b);
}
// for kernel predicates, to indicate a FT providing a division operator is required
struct FT_necessary {};
// To distinguish between kernel predicates for which a division-less FT is sufficient
template <typename T>
struct Needs_FT
{
T value;
Needs_FT(T v) : value(v) {}
operator T() const { return value; }
};
} //namespace CGAL
template <typename T>
struct Remove_needs_FT
{
using Type = T;
};
template <typename T>
struct Remove_needs_FT<Needs_FT<T> >
{
using Type = T;
};
} // namespace CGAL
#endif // CGAL_TAGS_H