mirror of https://github.com/CGAL/cgal
Integrate boost::variant with Lazy kernels interaction
This requires changing the way Lazy_construction_XXX wrappers are selected and some code to unpack variants.
This commit is contained in:
parent
8415eb6484
commit
a214d62bd6
|
|
@ -42,9 +42,6 @@
|
|||
#include <boost/variant.hpp>
|
||||
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/remove.hpp>
|
||||
#include <boost/mpl/back_inserter.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
|
||||
#include <boost/preprocessor/facilities/expand.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
|
||||
|
|
@ -53,9 +50,6 @@
|
|||
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
|
||||
#include <boost/preprocessor/repetition/enum.hpp>
|
||||
|
||||
// this needs to be removed
|
||||
#include <CGAL/Intersection_traits.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
template <typename AT, typename ET, typename EFT, typename E2A> class Lazy;
|
||||
|
|
@ -971,10 +965,8 @@ struct Ith_for_intersection_with_variant {
|
|||
const std::vector<T2>* ptr = (boost::get<std::vector<T2> >(&o));
|
||||
return (*ptr)[i];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
template <typename LK, typename AC, typename EC>
|
||||
struct Lazy_cartesian_const_iterator_2
|
||||
{
|
||||
|
|
@ -1361,122 +1353,112 @@ CGAL_Kernel_obj(Point_3)
|
|||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//____________________________________________________________
|
||||
// The magic functor that has Lazy<Something> as result type.
|
||||
// Two versions are distinguished: one that needs to fiddle
|
||||
// with result_of and another that can forward the result types.
|
||||
|
||||
namespace internal {
|
||||
// lift boost::get into a functor with a result_type member name and
|
||||
// extend it to operate on optionals
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
||||
|
||||
// TODO there is a mismatch between the result_type typedef and the
|
||||
// actual return type of operator()
|
||||
// lift boost::get into a functor with a result_type member name and
|
||||
// extend it to operate on optionals
|
||||
|
||||
// TODO there is a mismatch between the result_type typedef and the
|
||||
// actual return type of operator()
|
||||
template<typename T>
|
||||
struct Variant_cast {
|
||||
typedef T result_type;
|
||||
|
||||
template<BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
||||
const T&
|
||||
operator()(const boost::optional< boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) > >& o) const {
|
||||
// can throw but should never because we always build it inside
|
||||
// a static visitor with the right type
|
||||
return boost::get<T>(*o);
|
||||
}
|
||||
|
||||
template<BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
||||
T&
|
||||
operator()(boost::optional< boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) > >& o) const {
|
||||
// can throw but should never because we always build it inside
|
||||
// a static visitor with the right type, if it throws bad_get
|
||||
return boost::get<T>(*o);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Result, typename AK, typename LK, typename EK, typename Origin>
|
||||
struct Fill_lazy_variant_visitor_2 : boost::static_visitor<> {
|
||||
Fill_lazy_variant_visitor_2(Result& r, Origin& o) : r(&r), o(&o) {}
|
||||
Result* r;
|
||||
Origin* o;
|
||||
|
||||
template<typename T>
|
||||
struct Variant_cast {
|
||||
typedef T result_type;
|
||||
void operator()(const T&) {
|
||||
// the equivalent type we are currently matching in the lazy kernel
|
||||
typedef T AKT;
|
||||
typedef typename Type_mapper<AKT, AK, EK>::type EKT;
|
||||
typedef typename Type_mapper<AKT, AK, LK>::type LKT;
|
||||
|
||||
template<BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
||||
const T&
|
||||
operator()(const boost::optional< boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) > >& o) const {
|
||||
// can throw but should never because we always build it inside
|
||||
// a static visitor with the right type
|
||||
return boost::get<T>(*o);
|
||||
}
|
||||
|
||||
template<BOOST_VARIANT_ENUM_PARAMS(typename U)>
|
||||
T&
|
||||
operator()(boost::optional< boost::variant< BOOST_VARIANT_ENUM_PARAMS(U) > >& o) const {
|
||||
// can throw but should never because we always build it inside
|
||||
// a static visitor with the right type, if it throws bad_get
|
||||
return boost::get<T>(*o);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result, typename AK, typename LK, typename EK, typename Origin>
|
||||
struct Fill_lazy_variant_visitor_2 : boost::static_visitor<> {
|
||||
Fill_lazy_variant_visitor_2(Result& r, Origin& o) : r(&r), o(&o) {}
|
||||
Result* r;
|
||||
Origin* o;
|
||||
typedef Lazy_rep_1<AKT, EKT, Variant_cast<AKT>, Variant_cast<EKT>, typename LK::E2A, Origin> Lcr;
|
||||
Lcr * lcr = new Lcr(Variant_cast<AKT>(), Variant_cast<EKT>(), *o);
|
||||
|
||||
*r = LKT(lcr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T&) {
|
||||
// the equivalent type we are currently matching in the lazy kernel
|
||||
typedef T AKT;
|
||||
typedef typename Type_mapper<AKT, AK, EK>::type EKT;
|
||||
typedef typename Type_mapper<AKT, AK, LK>::type LKT;
|
||||
template<typename T>
|
||||
void operator()(const std::vector<T>& t) {
|
||||
typedef T AKT;
|
||||
typedef typename Type_mapper<AKT, AK, EK>::type EKT;
|
||||
typedef typename Type_mapper<AKT, AK, LK>::type LKT;
|
||||
|
||||
typedef Lazy_rep_1<Variant_cast<AKT>, Variant_cast<EKT>, typename LK::E2A, Origin> Lcr;
|
||||
Lcr * lcr = new Lcr(Variant_cast<AKT>(), Variant_cast<EKT>(), *o);
|
||||
|
||||
*r = LKT(lcr);
|
||||
std::vector<LKT> V;
|
||||
V.resize(t.size());
|
||||
for (unsigned int i = 0; i < t.size(); i++) {
|
||||
V[i] = LKT(new Lazy_rep_1<AKT, EKT, Ith_for_intersection<AKT>,
|
||||
Ith_for_intersection<EKT>, typename LK::E2A, Origin>
|
||||
(Ith_for_intersection<AKT>(i), Ith_for_intersection<EKT>(i), *o));
|
||||
}
|
||||
|
||||
*r = V;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result, typename AK, typename LK, typename EK>
|
||||
struct Fill_lazy_variant_visitor_0 : boost::static_visitor<> {
|
||||
Fill_lazy_variant_visitor_0(Result& r) : r(&r) {}
|
||||
Result* r;
|
||||
|
||||
template<typename T>
|
||||
void operator()(const std::vector<T>& t) {
|
||||
typedef T AKT;
|
||||
typedef typename Type_mapper<AKT, AK, EK>::type EKT;
|
||||
typedef typename Type_mapper<AKT, AK, LK>::type LKT;
|
||||
|
||||
std::vector<LKT> V;
|
||||
V.resize(t.size());
|
||||
for (unsigned int i = 0; i < t.size(); i++) {
|
||||
V[i] = LKT(new Lazy_rep_1<Ith_for_intersection<AKT>,
|
||||
Ith_for_intersection<EKT>, typename LK::E2A, Origin>
|
||||
(Ith_for_intersection<AKT>(i), Ith_for_intersection<EKT>(i), *o));
|
||||
}
|
||||
template<typename T>
|
||||
void operator()(const T& t) {
|
||||
// the equivalent type we are currently matching in the lazy kernel
|
||||
typedef T EKT;
|
||||
typedef typename Type_mapper<EKT, EK, AK>::type AKT;
|
||||
typedef typename Type_mapper<EKT, EK, LK>::type LKT;
|
||||
|
||||
*r = V;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Result, typename AK, typename LK, typename EK>
|
||||
struct Fill_lazy_variant_visitor_0 : boost::static_visitor<> {
|
||||
Fill_lazy_variant_visitor_0(Result& r) : r(&r) {}
|
||||
Result* r;
|
||||
|
||||
template<typename T>
|
||||
void operator()(const T& t) {
|
||||
// the equivalent type we are currently matching in the lazy kernel
|
||||
typedef T EKT;
|
||||
typedef typename Type_mapper<EKT, EK, AK>::type AKT;
|
||||
typedef typename Type_mapper<EKT, EK, LK>::type LKT;
|
||||
|
||||
*r = LKT(new Lazy_rep_0<AKT, EKT, typename LK::E2A>(t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void operator()(const std::vector<T>& t) {
|
||||
typedef T EKT;
|
||||
typedef typename Type_mapper<EKT, EK, AK>::type AKT;
|
||||
typedef typename Type_mapper<EKT, EK, LK>::type LKT;
|
||||
|
||||
std::vector<LKT> V;
|
||||
V.resize(t.size());
|
||||
for (unsigned int i = 0; i < t.size(); i++) {
|
||||
V[i] = LKT(new Lazy_rep_0<AKT, EKT, typename LK::E2A>(t[i]));
|
||||
|
||||
// Ith_for_intersection_with_variant<AKT>,
|
||||
// Ith_for_intersection_with_variant<EKT>, typename LK::E2A>
|
||||
// (Ith_for_intersection_with_variant<AKT>(i), Ith_for_intersection_with_variant<EKT>(i), t[i]));
|
||||
}
|
||||
|
||||
*r = V;
|
||||
}
|
||||
};
|
||||
|
||||
// metafunction to add a result_type typedef to a Intersect functor
|
||||
// as soon as the arguments are known
|
||||
template<typename T, typename Add>
|
||||
struct Add_result_type_fix {
|
||||
struct Extended_F : public T {
|
||||
typedef Add result_type;
|
||||
};
|
||||
|
||||
typedef Extended_F type;
|
||||
};
|
||||
*r = LKT(new Lazy_rep_0<AKT, EKT, typename LK::E2A>(t));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct is_optional : boost::mpl::false_{};
|
||||
void operator()(const std::vector<T>& t) {
|
||||
typedef T EKT;
|
||||
typedef typename Type_mapper<EKT, EK, AK>::type AKT;
|
||||
typedef typename Type_mapper<EKT, EK, LK>::type LKT;
|
||||
|
||||
template<typename T>
|
||||
struct is_optional<boost::optional<T> > : boost::mpl::true_{};
|
||||
}
|
||||
std::vector<LKT> V;
|
||||
V.resize(t.size());
|
||||
for (unsigned int i = 0; i < t.size(); i++) {
|
||||
V[i] = LKT(new Lazy_rep_0<AKT, EKT, typename LK::E2A>(t[i]));
|
||||
}
|
||||
|
||||
*r = V;
|
||||
}
|
||||
};
|
||||
|
||||
} // internal
|
||||
|
||||
template <typename LK, typename AC, typename EC>
|
||||
struct Lazy_construction_variant {
|
||||
|
|
@ -1487,68 +1469,21 @@ struct Lazy_construction_variant {
|
|||
typedef typename EK::FT EFT;
|
||||
typedef typename LK::E2A E2A;
|
||||
|
||||
// Forward the result meta function, without touching implementation
|
||||
// details, we steal the result of the exact functor, know that it
|
||||
// is a optional< variant > or variant, and transform the inner type
|
||||
// list to a LK Kernel types. Partly stolen from the
|
||||
// cartesian_converter and a candidate for consolidation.
|
||||
template<typename A, typename B>
|
||||
class Result {
|
||||
typedef typename EC::template Result< typename Type_mapper<A, LK, EK>::type,
|
||||
typename Type_mapper<B, LK, EK>::type >::Type Exact_type;
|
||||
public:
|
||||
// This is the solution that prevents include Intersection_traits
|
||||
// but is buggy right now
|
||||
|
||||
// typedef typename
|
||||
// boost::mpl::if_< internal::is_optional<Exact_type>,
|
||||
// boost::optional<
|
||||
// typename boost::make_variant_over<
|
||||
// typename internal::Transform_type_mapper<
|
||||
// typename boost::mpl::remove< typename Exact_type::value_type::types,
|
||||
// boost::detail::variant::void_,
|
||||
// boost::mpl::back_inserter< boost::mpl::vector0<> >
|
||||
// >::type
|
||||
// , EK, LK >::type
|
||||
// >::type
|
||||
// >,
|
||||
// typename boost::make_variant_over<
|
||||
// typename internal::Transform_type_mapper<
|
||||
// typename boost::mpl::remove< typename Exact_type::types,
|
||||
// boost::detail::variant::void_,
|
||||
// boost::mpl::back_inserter< boost::mpl::vector0<> >
|
||||
// >::type
|
||||
// , EK, LK >::type
|
||||
// >::type
|
||||
// >::type Type;
|
||||
|
||||
// This is hack around but requires the include
|
||||
typedef typename CGAL::IT<A, B>::result_type Type;
|
||||
typedef Type type;
|
||||
};
|
||||
|
||||
template <typename L1, typename L2>
|
||||
typename Result<L1, L2>::Type
|
||||
typename boost::result_of<Lazy_construction_variant(L1, L2)>::type
|
||||
operator()(const L1& l1, const L2& l2) const {
|
||||
|
||||
typedef typename Result< L1, L2 >::Type result_type;
|
||||
typedef typename AC::template Result< typename Type_mapper<L1, LK, AK>::type,
|
||||
typename Type_mapper<L2, LK, AK>::type >::Type AT;
|
||||
typedef typename EC::template Result< typename Type_mapper<L1, LK, EK>::type,
|
||||
typename Type_mapper<L2, LK, EK>::type >::Type ET;
|
||||
|
||||
typedef typename internal::Add_result_type_fix<AC, AT>::type AC_with_result_type;
|
||||
typedef typename internal::Add_result_type_fix<EC, ET>::type EC_with_result_type;
|
||||
|
||||
typedef typename boost::result_of<Lazy_construction_variant(L1, L2)>::type result_type;
|
||||
|
||||
typedef typename boost::result_of<AC(typename Type_mapper<L1, LK, AK>::type,
|
||||
typename Type_mapper<L2, LK, AK>::type)>::type AT;
|
||||
typedef typename boost::result_of<EC(typename Type_mapper<L1, LK, EK>::type,
|
||||
typename Type_mapper<L2, LK, EK>::type)>::type ET;
|
||||
|
||||
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
|
||||
Protect_FPU_rounding<Protection> P;
|
||||
|
||||
try {
|
||||
Lazy<AT, ET, EFT, E2A> lazy(
|
||||
new Lazy_rep_2<AC_with_result_type,
|
||||
EC_with_result_type, E2A,
|
||||
L1, L2>(AC_with_result_type(), EC_with_result_type(), l1, l2)
|
||||
);
|
||||
Lazy<AT, ET, EFT, E2A> lazy(new Lazy_rep_2<AT, ET, AC, EC, E2A, L1, L2>(AC(), EC(), l1, l2));
|
||||
|
||||
// the approximate result requires the trait with types from the AK
|
||||
AT approx_v = lazy.approx();
|
||||
|
|
@ -1576,35 +1511,26 @@ struct Lazy_construction_variant {
|
|||
return res;
|
||||
}
|
||||
|
||||
internal::Fill_lazy_variant_visitor_0< result_type, AK, LK, EK> visitor(res);
|
||||
internal::Fill_lazy_variant_visitor_0<result_type, AK, LK, EK> visitor(res);
|
||||
boost::apply_visitor(visitor, *exact_v);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// hardcoded for ternary plane intersection
|
||||
template <typename L1, typename L2, typename L3>
|
||||
boost::optional< boost::variant< typename LK::Point_3, typename LK::Line_3, typename LK::Plane_3 > >
|
||||
typename boost::result_of<Lazy_construction_variant(L1, L2, L3)>::type
|
||||
operator()(const L1& l1, const L2& l2, const L3& l3) const {
|
||||
typedef boost::optional< boost::variant< typename LK::Point_3, typename LK::Line_3, typename LK::Plane_3 > >
|
||||
result_type;
|
||||
typedef boost::optional< boost::variant< typename AK::Point_3, typename AK::Line_3, typename AK::Plane_3 > >
|
||||
AT;
|
||||
typedef boost::optional< boost::variant< typename EK::Point_3, typename EK::Line_3, typename EK::Plane_3 > >
|
||||
ET;
|
||||
typedef typename internal::Add_result_type_fix<AC, AT>::type AC_with_result_type;
|
||||
typedef typename internal::Add_result_type_fix<EC, ET>::type EC_with_result_type;
|
||||
typedef typename boost::result_of<Lazy_construction_variant(L1, L2, L3)>::type result_type;
|
||||
|
||||
typedef typename boost::result_of<AC(typename Type_mapper<L1, LK, AK>::type,
|
||||
typename Type_mapper<L2, LK, AK>::type,
|
||||
typename Type_mapper<L3, LK, AK>::type)>::type AT;
|
||||
typedef typename boost::result_of<EC(typename Type_mapper<L1, LK, EK>::type,
|
||||
typename Type_mapper<L2, LK, EK>::type,
|
||||
typename Type_mapper<L3, LK, EK>::type)>::type ET;
|
||||
|
||||
|
||||
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
|
||||
Protect_FPU_rounding<Protection> P;
|
||||
try {
|
||||
Lazy<AT, ET, EFT, E2A> lazy(
|
||||
new Lazy_rep_3<AC_with_result_type,
|
||||
EC_with_result_type, E2A,
|
||||
L1, L2, L3>(AC_with_result_type(), EC_with_result_type(), l1, l2, l3)
|
||||
);
|
||||
Lazy<AT, ET, EFT, E2A> lazy(new Lazy_rep_3<AT, ET, AC, EC, E2A, L1, L2, L3>(AC(), EC(), l1, l2, l3));
|
||||
|
||||
// the approximate result requires the trait with types from the AK
|
||||
AT approx_v = lazy.approx();
|
||||
|
|
@ -1637,17 +1563,24 @@ struct Lazy_construction_variant {
|
|||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename>
|
||||
struct result {
|
||||
// this does not default, if you want to make a lazy lazy-kernel,
|
||||
// you are on your own
|
||||
};
|
||||
|
||||
#define CGAL_RESULT(z, n, d) \
|
||||
template< typename F, BOOST_PP_ENUM_PARAMS(n, class T) > \
|
||||
struct result<F( BOOST_PP_ENUM_PARAMS(n, T) )> { \
|
||||
BOOST_PP_REPEAT(n, CGAL_TYPEMAP_AC, T) \
|
||||
typedef typename Type_mapper< \
|
||||
typename boost::result_of<AC( BOOST_PP_ENUM_PARAMS(n, A) )>::type, AK, LK>::type type; \
|
||||
};
|
||||
|
||||
BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_RESULT, _)
|
||||
};
|
||||
|
||||
//____________________________________________________________
|
||||
// The magic functor that has Lazy<Something> as result type.
|
||||
// Two versions are distinguished: one that needs to fiddle
|
||||
// with result_of and another that can forward the result types.
|
||||
|
||||
namespace internal {
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
|
||||
}
|
||||
|
||||
template<typename LK, typename AC, typename EC, typename E2A = Default,
|
||||
bool has_result_type = internal::has_result_type<AC>::value && internal::has_result_type<EC>::value >
|
||||
struct Lazy_construction;
|
||||
|
|
@ -1673,14 +1606,14 @@ struct Lazy_construction<LK, AC, EC, E2A_, true> {
|
|||
AC ac;
|
||||
EC ec;
|
||||
|
||||
#define CGAL_CONSTRUCTION_OPERATOR(z, n, d ) \
|
||||
#define CGAL_CONSTRUCTION_OPERATOR(z, n, d ) \
|
||||
template<BOOST_PP_ENUM_PARAMS(n, class L)> \
|
||||
result_type \
|
||||
operator()( BOOST_PP_ENUM(n, CGAL_LARGS, _) ) const { \
|
||||
typedef Lazy< AT, ET, EFT, E2A> Handle; \
|
||||
operator()( BOOST_PP_ENUM(n, CGAL_LARGS, _) ) const { \
|
||||
typedef Lazy< AT, ET, EFT, E2A> Handle; \
|
||||
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); \
|
||||
Protect_FPU_rounding<Protection> P; \
|
||||
try { \
|
||||
Protect_FPU_rounding<Protection> P; \
|
||||
try { \
|
||||
return result_type( Handle(new Lazy_rep_##n<AT, ET, AC, EC, E2A, BOOST_PP_ENUM_PARAMS(n, L)>(ac, ec, BOOST_PP_ENUM_PARAMS(n, l)))); \
|
||||
} catch (Uncertain_conversion_exception) { \
|
||||
CGAL_BRANCH_PROFILER_BRANCH(tmp); \
|
||||
|
|
|
|||
|
|
@ -32,16 +32,17 @@
|
|||
#include <CGAL/Filtered_kernel/Cartesian_coordinate_iterator_3.h>
|
||||
#include <CGAL/Lazy.h>
|
||||
|
||||
#include <boost/none.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/eval_if.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/type_traits/remove_reference.hpp>
|
||||
#include <boost/type_traits/remove_cv.hpp>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
namespace internal {
|
||||
|
||||
// SFINAE way to detect result_type typedefs.
|
||||
template<typename T>
|
||||
class Has_result_type_helper
|
||||
|
|
@ -68,43 +69,23 @@ struct Has_result_type
|
|||
Has_result_type_helper< typename boost::remove_cv<T>::type>::value>
|
||||
{};
|
||||
|
||||
template<bool has_result_type, typename F>
|
||||
struct Maybe_result_type {
|
||||
// This is incredibly evil. It relies on the fact that we always
|
||||
// have a type in the primary result template but it looks like the
|
||||
// only way out given the current design.
|
||||
typedef typename F::template result<void>::type type;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct Maybe_result_type<true, F> {
|
||||
typedef typename F::result_type type;
|
||||
};
|
||||
|
||||
// goes through the standard process of selecting the right
|
||||
// Lazy_something after the kind of the return type has been
|
||||
// determined
|
||||
template<typename T, typename AK, typename EK, typename Kernel, typename AKC, typename EKC>
|
||||
struct Standard_pick {
|
||||
typedef typename boost::remove_cv< typename boost::remove_reference< typename T::type >::type >::type T_;
|
||||
typedef typename boost::mpl::if_< boost::is_same< T_, typename AK::FT >,
|
||||
Lazy_construction_nt<Kernel, AKC, EKC>,
|
||||
typename boost::mpl::if_< boost::is_same< T_, Object >,
|
||||
Lazy_construction_object<Kernel, AKC, EKC>,
|
||||
Lazy_construction<Kernel, AKC, EKC> >::type
|
||||
>::type type;
|
||||
};
|
||||
|
||||
// accessor for result_type, to get a nullary meta function for use in eval_if
|
||||
template<typename T>
|
||||
struct Get_rs {
|
||||
template <typename T>
|
||||
struct Get_result_type {
|
||||
typedef typename T::result_type type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Get_lazy_rs : boost::mpl::eval_if< typename internal::Has_result_type< T >,
|
||||
typename internal::Get_rs< T >,
|
||||
typename boost::mpl::identity< T > > {};
|
||||
template <typename T>
|
||||
struct Lazy_result_type
|
||||
: boost::mpl::eval_if< Has_result_type<T>,
|
||||
Get_result_type<T>,
|
||||
boost::mpl::identity<void> >
|
||||
{};
|
||||
|
||||
class Enum_holder {
|
||||
protected:
|
||||
enum { NONE, NT, VARIANT, OBJECT, BBOX };
|
||||
};
|
||||
|
||||
} // internal
|
||||
|
||||
// Exact_kernel = exact kernel that will be made lazy
|
||||
|
|
@ -112,8 +93,8 @@ struct Get_lazy_rs : boost::mpl::eval_if< typename internal::Has_result_type< T
|
|||
|
||||
// the Generic base simplies applies the generic magic functor stupidly.
|
||||
// then the real base fixes up a few special cases.
|
||||
template < typename EK_, typename AK_, typename E2A_, typename Kernel >
|
||||
class Lazy_kernel_generic_base
|
||||
template < typename EK_, typename AK_, typename E2A_, typename Kernel_ >
|
||||
class Lazy_kernel_generic_base : protected internal::Enum_holder
|
||||
// : public Filtered_kernel_base<EK_>
|
||||
// TODO : Static_filters_base too ? Check performance
|
||||
{
|
||||
|
|
@ -122,14 +103,14 @@ public:
|
|||
typedef AK_ Approximate_kernel;
|
||||
typedef EK_ Exact_kernel;
|
||||
typedef E2A_ E2A;
|
||||
typedef Kernel_ Kernel;
|
||||
|
||||
// 3 synonyms identical to Filtered_kernel (TODO : cleanup !)
|
||||
// synonym identical to Filtered_kernel
|
||||
typedef AK_ FK;
|
||||
//typedef E2A_ C2F;
|
||||
|
||||
// Note: Approx_converter and Exact_converter are defined in <CGAL/Lazy.h>
|
||||
typedef Approx_converter<Kernel, Approximate_kernel> C2F;
|
||||
typedef Exact_converter<Kernel, Exact_kernel> C2E;
|
||||
// Note: Approx_converter and Exact_converter are defined in <CGAL/Lazy.h>
|
||||
|
||||
template < typename Kernel2 >
|
||||
struct Base { typedef Lazy_kernel_generic_base<Exact_kernel, Approximate_kernel, E2A, Kernel2> Type; };
|
||||
|
|
@ -144,10 +125,6 @@ public:
|
|||
typedef typename T::Feature_dimension type;
|
||||
};
|
||||
|
||||
// What to do with the tag ?
|
||||
// Probably this should not exist, should it ?
|
||||
// struct filter_tag{};
|
||||
// typedef filter_tag Kernel_tag;
|
||||
typedef typename Exact_kernel::Kernel_tag Kernel_tag;
|
||||
typedef typename Exact_kernel::Rep_tag Rep_tag;
|
||||
|
||||
|
|
@ -193,6 +170,93 @@ public:
|
|||
typedef CGAL::Aff_transformationC2<Kernel> Aff_transformation_2;
|
||||
typedef CGAL::Aff_transformationC3<Kernel> Aff_transformation_3;
|
||||
|
||||
private:
|
||||
// We use a combination of partial and logic to extract the right
|
||||
// construction. Constructions without a result_type always have to
|
||||
// be done through specializations.
|
||||
//
|
||||
// The case distinction goes as follows:
|
||||
// result_type == FT => NT
|
||||
// result_type == Object => Object
|
||||
// result_type == Bbox_2 || result_type == Bbox_3 => BBOX
|
||||
// default => NONE
|
||||
// no result_type => NONE
|
||||
//
|
||||
//
|
||||
// we require a Dummy because we cannot have complete
|
||||
// specializations inside a non-namespace scope.
|
||||
// The default implementation does some default handling,
|
||||
// the special cases are filtered by partial specializations.
|
||||
template <typename Construction, typename Dummy = boost::none_t>
|
||||
struct Lazy_wrapper_traits :
|
||||
boost::mpl::eval_if< internal::Has_result_type<Construction>,
|
||||
boost::mpl::eval_if< boost::is_same< typename boost::remove_cv<
|
||||
typename boost::remove_reference<
|
||||
typename internal::Lazy_result_type<Construction>::type
|
||||
>::type >::type,
|
||||
typename Approximate_kernel::FT>,
|
||||
boost::mpl::int_<NT>,
|
||||
boost::mpl::eval_if< boost::is_same< typename internal::Lazy_result_type<Construction>::type,
|
||||
CGAL::Object >,
|
||||
boost::mpl::int_<OBJECT>,
|
||||
boost::mpl::eval_if< boost::mpl::or_<
|
||||
boost::is_same< typename internal::Lazy_result_type<Construction>::type, CGAL::Bbox_2 >,
|
||||
boost::is_same< typename internal::Lazy_result_type<Construction>::type, CGAL::Bbox_3 > >,
|
||||
boost::mpl::int_<BBOX>,
|
||||
boost::mpl::int_<NONE> > > >,
|
||||
boost::mpl::int_<NONE> >::type {};
|
||||
|
||||
#define CGAL_WRAPPER_TRAIT(NAME, WRAPPER) \
|
||||
template<typename Dummy> \
|
||||
struct Lazy_wrapper_traits<typename Approximate_kernel::NAME, Dummy> \
|
||||
: boost::mpl::int_<WRAPPER> {};
|
||||
|
||||
CGAL_WRAPPER_TRAIT(Intersect_2, VARIANT)
|
||||
CGAL_WRAPPER_TRAIT(Intersect_3, VARIANT)
|
||||
CGAL_WRAPPER_TRAIT(Compute_squared_radius_2, NT)
|
||||
CGAL_WRAPPER_TRAIT(Compute_x_3, NT)
|
||||
CGAL_WRAPPER_TRAIT(Compute_y_3, NT)
|
||||
CGAL_WRAPPER_TRAIT(Compute_z_3, NT)
|
||||
|
||||
#undef CGAL_WRAPPER_TRAIT
|
||||
|
||||
template <typename Construction, int Type = Lazy_wrapper_traits<Construction>::value>
|
||||
struct Select_wrapper_impl;
|
||||
|
||||
template <typename Construction>
|
||||
struct Select_wrapper_impl<Construction, NONE> {
|
||||
template<typename Kernel, typename AKC, typename EKC>
|
||||
struct apply { typedef Lazy_construction<Kernel, AKC, EKC> type; };
|
||||
};
|
||||
|
||||
template <typename Construction>
|
||||
struct Select_wrapper_impl<Construction, NT> {
|
||||
template<typename Kernel, typename AKC, typename EKC>
|
||||
struct apply { typedef Lazy_construction_nt<Kernel, AKC, EKC> type; };
|
||||
};
|
||||
|
||||
template <typename Construction>
|
||||
struct Select_wrapper_impl<Construction, VARIANT> {
|
||||
template<typename Kernel, typename AKC, typename EKC>
|
||||
struct apply { typedef Lazy_construction_variant<Kernel, AKC, EKC> type; };
|
||||
};
|
||||
|
||||
template <typename Construction>
|
||||
struct Select_wrapper_impl<Construction, OBJECT> {
|
||||
template<typename Kernel, typename AKC, typename EKC>
|
||||
struct apply { typedef Lazy_construction_object<Kernel, AKC, EKC> type; };
|
||||
};
|
||||
|
||||
template <typename Construction>
|
||||
struct Select_wrapper_impl<Construction, BBOX> {
|
||||
template<typename Kernel, typename AKC, typename EKC>
|
||||
struct apply { typedef Lazy_construction_bbox<Kernel, AKC, EKC> type; };
|
||||
};
|
||||
|
||||
template <typename Construction>
|
||||
struct Select_wrapper : Select_wrapper_impl<Construction> {};
|
||||
|
||||
public:
|
||||
|
||||
// We don't touch the predicates.
|
||||
// FIXME TODO : better use a layer of Filtered_kernel on top of everything,
|
||||
|
|
@ -201,46 +265,10 @@ public:
|
|||
typedef Filtered_predicate<typename Exact_kernel::P, typename Approximate_kernel::P, C2E, C2F> P; \
|
||||
P Pf() const { return P(); }
|
||||
|
||||
// We change the constructions.
|
||||
#ifdef CGAL_INTERSECT_WITH_ITERATORS_2
|
||||
#define CGAL_Kernel_cons(C, Cf) \
|
||||
typedef typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C, typename Approximate_kernel::Intersect_with_iterators_2>, \
|
||||
Lazy_intersect_with_iterators<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Bbox_2>, \
|
||||
Lazy_construction_bbox<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, typename Approximate_kernel::FT>,\
|
||||
Lazy_construction_nt<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>,\
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Object >,\
|
||||
Lazy_construction_object<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>,\
|
||||
Lazy_construction<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C> >::type >::type > ::type > ::type C; \
|
||||
C Cf() const { return C(); }
|
||||
|
||||
CGAL_Kernel_cons(Intersect_with_iterators_2,
|
||||
intersect_with_iterators_2_object)
|
||||
#else
|
||||
// This does the following: If the Construction has a result_type
|
||||
// member, do the eval_if dance, otherwise we have (hopefully) a
|
||||
// variant result_type. The inner eval_if dance is necessary to
|
||||
// prevent the compiler from trying to instantiate the result_type
|
||||
// if it isn't actually there. The true branch of the outer most if
|
||||
// evaluates to either Lazy_construction_object,
|
||||
// Lazy_construction_nt or Lazy_construction; depending on the
|
||||
// result_type.
|
||||
#define CGAL_Kernel_cons(C, Cf) \
|
||||
typedef typename boost::mpl::if_< internal::Has_result_type< typename Approximate_kernel::C >, \
|
||||
typename boost::mpl::if_< boost::is_same< typename internal::Get_lazy_rs< typename Approximate_kernel::C >::type , \
|
||||
typename Approximate_kernel::FT >, \
|
||||
Lazy_construction_nt< Kernel, typename Approximate_kernel::C, typename Exact_kernel::C >, \
|
||||
typename boost::mpl::if_< boost::is_same< typename internal::Get_lazy_rs< typename Approximate_kernel::C >::type, \
|
||||
typename CGAL::Object >, \
|
||||
Lazy_construction_object< Kernel,typename Approximate_kernel::C, typename Exact_kernel::C >, \
|
||||
Lazy_construction< Kernel,typename Approximate_kernel::C, typename Exact_kernel::C > >::type \
|
||||
>::type, \
|
||||
Lazy_construction_variant< Kernel, typename Approximate_kernel::C, typename Exact_kernel::C > >::type C; \
|
||||
typedef typename Select_wrapper<typename Approximate_kernel::C>::template apply<Kernel, typename Approximate_kernel::C, typename Exact_kernel::C>::type C; \
|
||||
C Cf() const { return C(); }
|
||||
|
||||
#endif //CGAL_INTERSECT_WITH_ITERATORS_2
|
||||
|
||||
#include <CGAL/Kernel/interface_macros.h>
|
||||
};
|
||||
|
||||
|
|
@ -257,44 +285,6 @@ public:
|
|||
template < typename Kernel2 >
|
||||
struct Base { typedef Lazy_kernel_base<Exact_kernel, Approximate_kernel, E2A, Kernel2> Type; };
|
||||
|
||||
#if 0
|
||||
// We change the constructions.
|
||||
#ifdef CGAL_INTERSECT_WITH_ITERATORS_2
|
||||
#define CGAL_Kernel_cons(C, Cf) \
|
||||
typedef typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C, typename Approximate_kernel::Intersect_with_iterators_2>, \
|
||||
Lazy_intersect_with_iterators<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Bbox_2>, \
|
||||
Lazy_construction_bbox<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, typename Approximate_kernel::FT>,\
|
||||
Lazy_construction_nt<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>,\
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Object >,\
|
||||
Lazy_construction_object<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>,\
|
||||
Lazy_construction<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C> >::type >::type > ::type > ::type C; \
|
||||
C Cf() const { return C(); }
|
||||
|
||||
CGAL_Kernel_cons(Intersect_with_iterators_2,
|
||||
intersect_with_iterators_2_object)
|
||||
#else
|
||||
#define CGAL_Kernel_cons(C, Cf) \
|
||||
typedef typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C, typename Approximate_kernel::Construct_cartesian_const_iterator_2>, \
|
||||
Lazy_cartesian_const_iterator_2<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C, typename Approximate_kernel::Construct_cartesian_const_iterator_3>, \
|
||||
Lazy_cartesian_const_iterator_3<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Bbox_2>, \
|
||||
Lazy_construction_bbox<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Bbox_3>, \
|
||||
Lazy_construction_bbox<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>, \
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, typename Approximate_kernel::FT>,\
|
||||
Lazy_construction_nt<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>,\
|
||||
typename boost::mpl::if_<boost::is_same<typename Approximate_kernel::C::result_type, Object >,\
|
||||
Lazy_construction_object<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C>,\
|
||||
Lazy_construction<Kernel,typename Approximate_kernel::C, typename Exact_kernel::C> >::type >::type >::type > ::type > ::type > ::type C; \
|
||||
C Cf() const { return C(); }
|
||||
|
||||
#endif //CGAL_INTERSECT_WITH_ITERATORS_2
|
||||
|
||||
#endif // 0
|
||||
|
||||
typedef CommonKernelFunctors::Assign_2<Kernel> Assign_2;
|
||||
typedef CommonKernelFunctors::Assign_3<Kernel> Assign_3;
|
||||
typedef Lazy_construction_bbox<Kernel, typename Approximate_kernel::Construct_bbox_2, typename Exact_kernel::Construct_bbox_2> Construct_bbox_2;
|
||||
|
|
|
|||
|
|
@ -69,21 +69,21 @@
|
|||
#define CGAL_INTERSECTION_FUNCTION(A, B, DIM) \
|
||||
template<typename K> \
|
||||
inline \
|
||||
typename BOOST_PP_CAT(K::Intersect_, DIM)::template Result<typename K::A, typename K::B>::Type \
|
||||
intersection(const A<K>& a, const B<K>& b) { \
|
||||
typename boost::result_of<BOOST_PP_CAT(typename K::Intersect_, DIM)(typename K::A, typename K::B)>::type \
|
||||
intersection(const A<K>& a, const B<K>& b) { \
|
||||
return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
|
||||
} \
|
||||
template<typename K> \
|
||||
inline \
|
||||
typename BOOST_PP_CAT(K::Intersect_, DIM)::template Result<typename K::A, typename K::B>::Type \
|
||||
intersection(const B<K>& a, const A<K>& b) { \
|
||||
typename boost::result_of<BOOST_PP_CAT(typename K::Intersect_, DIM)(typename K::A, typename K::B)>::type \
|
||||
intersection(const B<K>& a, const A<K>& b) { \
|
||||
return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
|
||||
}
|
||||
|
||||
#define CGAL_INTERSECTION_FUNCTION_SELF(A, DIM) \
|
||||
template<typename K> \
|
||||
inline \
|
||||
typename BOOST_PP_CAT(K::Intersect_, DIM)::template Result<typename K::A, typename K::A>::Type \
|
||||
typename boost::result_of<BOOST_PP_CAT(typename K::Intersect_, DIM)(typename K::A, typename K::A)>::type \
|
||||
intersection(const A<K> & a, const A<K> & b) { \
|
||||
return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ namespace CGAL {
|
|||
// only declarationn
|
||||
template<typename, typename, typename>
|
||||
struct Intersection_traits {
|
||||
// This defaults to Object, if we use VERSION < 2 and to nothing
|
||||
// This defaults to Object, if we use VERSION < 2 and do nothing
|
||||
// otherwise.
|
||||
#if CGAL_INTERSECTION_VERSION < 2
|
||||
typedef CGAL::Object result_type;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
#include <CGAL/basic.h>
|
||||
#include <CGAL/use.h>
|
||||
#include <CGAL/Cartesian.h>
|
||||
#include <CGAL/intersections.h>
|
||||
#include <CGAL/Bbox_3.h>
|
||||
|
|
@ -24,8 +26,12 @@ typedef CGAL::Bbox_3 Bbox_3;
|
|||
|
||||
template<class A, class B>
|
||||
void call_intersection_global(const A& a, const B& b) {
|
||||
typename CGAL::IT<A, B>::result_type x = CGAL::intersection(a, b);
|
||||
typename CGAL::IT<A, B>::result_type y = CGAL::intersection(b, a);
|
||||
typename boost::result_of<K::Intersect_3(A, B)>::type x =CGAL::intersection(a, b);
|
||||
typename boost::result_of<K::Intersect_3(A, B)>::type y =CGAL::intersection(b, a);
|
||||
typename boost::result_of<K::Intersect_3(B, A)>::type z =CGAL::intersection(b, a);
|
||||
CGAL_USE(x);
|
||||
CGAL_USE(y);
|
||||
CGAL_USE(z);
|
||||
}
|
||||
|
||||
template<class A, class B>
|
||||
|
|
|
|||
|
|
@ -201,9 +201,8 @@ proper_subset(Interval interval1, Interval interval2) {
|
|||
template<typename Interval> inline
|
||||
typename Interval_traits<Interval>::Intersection::result_type
|
||||
intersection(Interval interval1, Interval interval2, typename boost::enable_if<
|
||||
boost::is_same<
|
||||
typename Interval_traits<Interval>::Is_interval,
|
||||
Tag_true > >::type* = NULL
|
||||
typename Interval_traits<Interval>::Is_interval
|
||||
>::type* = NULL
|
||||
) {
|
||||
typename Interval_traits<Interval>::Intersection intersection;
|
||||
return intersection(interval1, interval2);
|
||||
|
|
|
|||
|
|
@ -2524,11 +2524,12 @@ namespace CommonKernelFunctors {
|
|||
class Intersect_2
|
||||
{
|
||||
public:
|
||||
template<typename A, typename B>
|
||||
struct Result {
|
||||
typedef typename Intersection_traits<K, A, B>::result_type Type;
|
||||
// Boost MPL compatibility
|
||||
typedef Type type;
|
||||
template<typename>
|
||||
struct result;
|
||||
|
||||
template<typename F, typename A, typename B>
|
||||
struct result<F(A,B)> {
|
||||
typedef typename Intersection_traits<K, A, B>::result_type type;
|
||||
};
|
||||
|
||||
// Solely to make the lazy kernel work
|
||||
|
|
@ -2538,7 +2539,7 @@ namespace CommonKernelFunctors {
|
|||
|
||||
// 25 possibilities, so I keep the template.
|
||||
template <class T1, class T2>
|
||||
typename Result< T1, T2 >::Type
|
||||
typename boost::result_of< Intersect_2(T1, T2) >::type
|
||||
operator()(const T1& t1, const T2& t2) const
|
||||
{ return internal::intersection(t1, t2, K()); }
|
||||
};
|
||||
|
|
@ -2548,11 +2549,20 @@ namespace CommonKernelFunctors {
|
|||
{
|
||||
typedef typename K::Plane_3 Plane_3;
|
||||
public:
|
||||
template<typename A, typename B>
|
||||
struct Result {
|
||||
typedef typename Intersection_traits<K, A, B>::result_type Type;
|
||||
// Boost MPL compatibility
|
||||
typedef Type type;
|
||||
template<typename>
|
||||
struct result;
|
||||
|
||||
template<typename F, typename A, typename B>
|
||||
struct result<F(A, B)> {
|
||||
typedef typename Intersection_traits<K, A, B>::result_type type;
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
struct result<F(Plane_3, Plane_3, Plane_3)> {
|
||||
typedef boost::optional<
|
||||
boost::variant< typename K::Point_3,
|
||||
typename K::Line_3,
|
||||
typename K::Plane_3 > > type;
|
||||
};
|
||||
|
||||
// Solely to make the lazy kernel work
|
||||
|
|
@ -2562,7 +2572,7 @@ namespace CommonKernelFunctors {
|
|||
|
||||
// n possibilities, so I keep the template.
|
||||
template <class T1, class T2>
|
||||
typename Result< T1, T2 >::Type
|
||||
typename boost::result_of< Intersect_3(T1, T2) >::type
|
||||
operator()(const T1& t1, const T2& t2) const
|
||||
{ return internal::intersection(t1, t2, K() ); }
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue