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:
Philipp Möller 2012-12-06 14:32:59 +01:00
parent 8415eb6484
commit a214d62bd6
6 changed files with 284 additions and 346 deletions

View File

@ -42,9 +42,6 @@
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <boost/mpl/has_xxx.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/facilities/expand.hpp>
#include <boost/preprocessor/repetition/repeat_from_to.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_binary_params.hpp>
#include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum.hpp>
// this needs to be removed
#include <CGAL/Intersection_traits.h>
namespace CGAL { namespace CGAL {
template <typename AT, typename ET, typename EFT, typename E2A> class Lazy; 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)); const std::vector<T2>* ptr = (boost::get<std::vector<T2> >(&o));
return (*ptr)[i]; return (*ptr)[i];
} }
}; };
template <typename LK, typename AC, typename EC> template <typename LK, typename AC, typename EC>
struct Lazy_cartesian_const_iterator_2 struct Lazy_cartesian_const_iterator_2
{ {
@ -1361,7 +1353,16 @@ 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 { namespace internal {
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type)
// lift boost::get into a functor with a result_type member name and // lift boost::get into a functor with a result_type member name and
// extend it to operate on optionals // extend it to operate on optionals
@ -1388,6 +1389,7 @@ namespace internal {
} }
}; };
template<typename Result, typename AK, typename LK, typename EK, typename Origin> template<typename Result, typename AK, typename LK, typename EK, typename Origin>
struct Fill_lazy_variant_visitor_2 : boost::static_visitor<> { struct Fill_lazy_variant_visitor_2 : boost::static_visitor<> {
Fill_lazy_variant_visitor_2(Result& r, Origin& o) : r(&r), o(&o) {} Fill_lazy_variant_visitor_2(Result& r, Origin& o) : r(&r), o(&o) {}
@ -1401,7 +1403,7 @@ namespace internal {
typedef typename Type_mapper<AKT, AK, EK>::type EKT; typedef typename Type_mapper<AKT, AK, EK>::type EKT;
typedef typename Type_mapper<AKT, AK, LK>::type LKT; typedef typename Type_mapper<AKT, AK, LK>::type LKT;
typedef Lazy_rep_1<Variant_cast<AKT>, Variant_cast<EKT>, typename LK::E2A, Origin> Lcr; 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); Lcr * lcr = new Lcr(Variant_cast<AKT>(), Variant_cast<EKT>(), *o);
*r = LKT(lcr); *r = LKT(lcr);
@ -1416,7 +1418,7 @@ namespace internal {
std::vector<LKT> V; std::vector<LKT> V;
V.resize(t.size()); V.resize(t.size());
for (unsigned int i = 0; i < t.size(); i++) { for (unsigned int i = 0; i < t.size(); i++) {
V[i] = LKT(new Lazy_rep_1<Ith_for_intersection<AKT>, V[i] = LKT(new Lazy_rep_1<AKT, EKT, Ith_for_intersection<AKT>,
Ith_for_intersection<EKT>, typename LK::E2A, Origin> Ith_for_intersection<EKT>, typename LK::E2A, Origin>
(Ith_for_intersection<AKT>(i), Ith_for_intersection<EKT>(i), *o)); (Ith_for_intersection<AKT>(i), Ith_for_intersection<EKT>(i), *o));
} }
@ -1450,33 +1452,13 @@ namespace internal {
V.resize(t.size()); V.resize(t.size());
for (unsigned int i = 0; i < t.size(); i++) { for (unsigned int i = 0; i < t.size(); i++) {
V[i] = LKT(new Lazy_rep_0<AKT, EKT, typename LK::E2A>(t[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; *r = V;
} }
}; };
// metafunction to add a result_type typedef to a Intersect functor } // internal
// 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;
};
template<typename T>
struct is_optional : boost::mpl::false_{};
template<typename T>
struct is_optional<boost::optional<T> > : boost::mpl::true_{};
}
template <typename LK, typename AC, typename EC> template <typename LK, typename AC, typename EC>
struct Lazy_construction_variant { struct Lazy_construction_variant {
@ -1487,68 +1469,21 @@ struct Lazy_construction_variant {
typedef typename EK::FT EFT; typedef typename EK::FT EFT;
typedef typename LK::E2A E2A; 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> 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 { operator()(const L1& l1, const L2& l2) const {
typedef typename boost::result_of<Lazy_construction_variant(L1, L2)>::type result_type;
typedef typename Result< L1, L2 >::Type result_type; typedef typename boost::result_of<AC(typename Type_mapper<L1, LK, AK>::type,
typedef typename AC::template Result< typename Type_mapper<L1, LK, AK>::type, typename Type_mapper<L2, LK, AK>::type)>::type AT;
typename Type_mapper<L2, LK, AK>::type >::Type AT; typedef typename boost::result_of<EC(typename Type_mapper<L1, LK, EK>::type,
typedef typename EC::template Result< typename Type_mapper<L1, LK, EK>::type, typename Type_mapper<L2, LK, EK>::type)>::type ET;
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;
CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp);
Protect_FPU_rounding<Protection> P; Protect_FPU_rounding<Protection> P;
try { try {
Lazy<AT, ET, EFT, E2A> lazy( Lazy<AT, ET, EFT, E2A> lazy(new Lazy_rep_2<AT, ET, AC, EC, E2A, L1, L2>(AC(), EC(), l1, l2));
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)
);
// the approximate result requires the trait with types from the AK // the approximate result requires the trait with types from the AK
AT approx_v = lazy.approx(); AT approx_v = lazy.approx();
@ -1582,29 +1517,20 @@ struct Lazy_construction_variant {
} }
} }
// hardcoded for ternary plane intersection
template <typename L1, typename L2, typename L3> 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 { 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 > > typedef typename boost::result_of<Lazy_construction_variant(L1, L2, L3)>::type result_type;
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<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 { try {
Lazy<AT, ET, EFT, E2A> lazy( Lazy<AT, ET, EFT, E2A> lazy(new Lazy_rep_3<AT, ET, AC, EC, E2A, L1, L2, L3>(AC(), EC(), l1, l2, l3));
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)
);
// the approximate result requires the trait with types from the AK // the approximate result requires the trait with types from the AK
AT approx_v = lazy.approx(); AT approx_v = lazy.approx();
@ -1637,16 +1563,23 @@ struct Lazy_construction_variant {
return res; 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) \
// The magic functor that has Lazy<Something> as result type. template< typename F, BOOST_PP_ENUM_PARAMS(n, class T) > \
// Two versions are distinguished: one that needs to fiddle struct result<F( BOOST_PP_ENUM_PARAMS(n, T) )> { \
// with result_of and another that can forward the result types. 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; \
};
namespace internal { BOOST_PP_REPEAT_FROM_TO(1, 9, CGAL_RESULT, _)
BOOST_MPL_HAS_XXX_TRAIT_DEF(result_type) };
}
template<typename LK, typename AC, typename EC, typename E2A = Default, 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 > bool has_result_type = internal::has_result_type<AC>::value && internal::has_result_type<EC>::value >

View File

@ -32,16 +32,17 @@
#include <CGAL/Filtered_kernel/Cartesian_coordinate_iterator_3.h> #include <CGAL/Filtered_kernel/Cartesian_coordinate_iterator_3.h>
#include <CGAL/Lazy.h> #include <CGAL/Lazy.h>
#include <boost/none.hpp>
#include <boost/mpl/if.hpp> #include <boost/mpl/if.hpp>
#include <boost/mpl/eval_if.hpp> #include <boost/mpl/or.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/remove_reference.hpp> #include <boost/type_traits/remove_reference.hpp>
#include <boost/type_traits/remove_cv.hpp> #include <boost/type_traits/remove_cv.hpp>
namespace CGAL { namespace CGAL {
namespace internal { namespace internal {
// SFINAE way to detect result_type typedefs. // SFINAE way to detect result_type typedefs.
template<typename T> template<typename T>
class Has_result_type_helper class Has_result_type_helper
@ -68,43 +69,23 @@ struct Has_result_type
Has_result_type_helper< typename boost::remove_cv<T>::type>::value> 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> template <typename T>
struct Get_rs { struct Get_result_type {
typedef typename T::result_type type; typedef typename T::result_type type;
}; };
template <typename T> template <typename T>
struct Get_lazy_rs : boost::mpl::eval_if< typename internal::Has_result_type< T >, struct Lazy_result_type
typename internal::Get_rs< T >, : boost::mpl::eval_if< Has_result_type<T>,
typename boost::mpl::identity< T > > {}; Get_result_type<T>,
boost::mpl::identity<void> >
{};
class Enum_holder {
protected:
enum { NONE, NT, VARIANT, OBJECT, BBOX };
};
} // internal } // internal
// Exact_kernel = exact kernel that will be made lazy // 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. // the Generic base simplies applies the generic magic functor stupidly.
// then the real base fixes up a few special cases. // then the real base fixes up a few special cases.
template < typename EK_, typename AK_, typename E2A_, typename Kernel > template < typename EK_, typename AK_, typename E2A_, typename Kernel_ >
class Lazy_kernel_generic_base class Lazy_kernel_generic_base : protected internal::Enum_holder
// : public Filtered_kernel_base<EK_> // : public Filtered_kernel_base<EK_>
// TODO : Static_filters_base too ? Check performance // TODO : Static_filters_base too ? Check performance
{ {
@ -122,14 +103,14 @@ public:
typedef AK_ Approximate_kernel; typedef AK_ Approximate_kernel;
typedef EK_ Exact_kernel; typedef EK_ Exact_kernel;
typedef E2A_ E2A; typedef E2A_ E2A;
typedef Kernel_ Kernel;
// 3 synonyms identical to Filtered_kernel (TODO : cleanup !) // synonym identical to Filtered_kernel
typedef AK_ FK; 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 Approx_converter<Kernel, Approximate_kernel> C2F;
typedef Exact_converter<Kernel, Exact_kernel> C2E; typedef Exact_converter<Kernel, Exact_kernel> C2E;
// Note: Approx_converter and Exact_converter are defined in <CGAL/Lazy.h>
template < typename Kernel2 > template < typename Kernel2 >
struct Base { typedef Lazy_kernel_generic_base<Exact_kernel, Approximate_kernel, E2A, Kernel2> Type; }; 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; 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::Kernel_tag Kernel_tag;
typedef typename Exact_kernel::Rep_tag Rep_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_transformationC2<Kernel> Aff_transformation_2;
typedef CGAL::Aff_transformationC3<Kernel> Aff_transformation_3; 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. // We don't touch the predicates.
// FIXME TODO : better use a layer of Filtered_kernel on top of everything, // 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; \ typedef Filtered_predicate<typename Exact_kernel::P, typename Approximate_kernel::P, C2E, C2F> P; \
P Pf() const { return P(); } P Pf() const { return P(); }
// We change the constructions.
#ifdef CGAL_INTERSECT_WITH_ITERATORS_2
#define CGAL_Kernel_cons(C, Cf) \ #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>, \ typedef typename Select_wrapper<typename Approximate_kernel::C>::template apply<Kernel, typename Approximate_kernel::C, typename Exact_kernel::C>::type C; \
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(); } 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; \
C Cf() const { return C(); }
#endif //CGAL_INTERSECT_WITH_ITERATORS_2
#include <CGAL/Kernel/interface_macros.h> #include <CGAL/Kernel/interface_macros.h>
}; };
@ -257,44 +285,6 @@ public:
template < typename Kernel2 > template < typename Kernel2 >
struct Base { typedef Lazy_kernel_base<Exact_kernel, Approximate_kernel, E2A, Kernel2> Type; }; 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_2<Kernel> Assign_2;
typedef CommonKernelFunctors::Assign_3<Kernel> Assign_3; 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; typedef Lazy_construction_bbox<Kernel, typename Approximate_kernel::Construct_bbox_2, typename Exact_kernel::Construct_bbox_2> Construct_bbox_2;

View File

@ -69,13 +69,13 @@
#define CGAL_INTERSECTION_FUNCTION(A, B, DIM) \ #define CGAL_INTERSECTION_FUNCTION(A, B, DIM) \
template<typename K> \ template<typename K> \
inline \ inline \
typename BOOST_PP_CAT(K::Intersect_, DIM)::template Result<typename K::A, typename K::B>::Type \ 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) { \ intersection(const A<K>& a, const B<K>& b) { \
return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
} \ } \
template<typename K> \ template<typename K> \
inline \ inline \
typename BOOST_PP_CAT(K::Intersect_, DIM)::template Result<typename K::A, typename K::B>::Type \ 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) { \ intersection(const B<K>& a, const A<K>& b) { \
return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
} }
@ -83,7 +83,7 @@
#define CGAL_INTERSECTION_FUNCTION_SELF(A, DIM) \ #define CGAL_INTERSECTION_FUNCTION_SELF(A, DIM) \
template<typename K> \ template<typename K> \
inline \ 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) { \ intersection(const A<K> & a, const A<K> & b) { \
return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \ return BOOST_PP_CAT(K().intersect_, BOOST_PP_CAT(DIM, _object()(a, b))); \
} }
@ -112,7 +112,7 @@ namespace CGAL {
// only declarationn // only declarationn
template<typename, typename, typename> template<typename, typename, typename>
struct Intersection_traits { 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. // otherwise.
#if CGAL_INTERSECTION_VERSION < 2 #if CGAL_INTERSECTION_VERSION < 2
typedef CGAL::Object result_type; typedef CGAL::Object result_type;

View File

@ -1,3 +1,5 @@
#include <CGAL/basic.h>
#include <CGAL/use.h>
#include <CGAL/Cartesian.h> #include <CGAL/Cartesian.h>
#include <CGAL/intersections.h> #include <CGAL/intersections.h>
#include <CGAL/Bbox_3.h> #include <CGAL/Bbox_3.h>
@ -24,8 +26,12 @@ typedef CGAL::Bbox_3 Bbox_3;
template<class A, class B> template<class A, class B>
void call_intersection_global(const A& a, const B& b) { void call_intersection_global(const A& a, const B& b) {
typename CGAL::IT<A, B>::result_type x = CGAL::intersection(a, b); typename boost::result_of<K::Intersect_3(A, B)>::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 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> template<class A, class B>

View File

@ -201,9 +201,8 @@ proper_subset(Interval interval1, Interval interval2) {
template<typename Interval> inline template<typename Interval> inline
typename Interval_traits<Interval>::Intersection::result_type typename Interval_traits<Interval>::Intersection::result_type
intersection(Interval interval1, Interval interval2, typename boost::enable_if< intersection(Interval interval1, Interval interval2, typename boost::enable_if<
boost::is_same< typename Interval_traits<Interval>::Is_interval
typename Interval_traits<Interval>::Is_interval, >::type* = NULL
Tag_true > >::type* = NULL
) { ) {
typename Interval_traits<Interval>::Intersection intersection; typename Interval_traits<Interval>::Intersection intersection;
return intersection(interval1, interval2); return intersection(interval1, interval2);

View File

@ -2524,11 +2524,12 @@ namespace CommonKernelFunctors {
class Intersect_2 class Intersect_2
{ {
public: public:
template<typename A, typename B> template<typename>
struct Result { struct result;
typedef typename Intersection_traits<K, A, B>::result_type Type;
// Boost MPL compatibility template<typename F, typename A, typename B>
typedef Type type; struct result<F(A,B)> {
typedef typename Intersection_traits<K, A, B>::result_type type;
}; };
// Solely to make the lazy kernel work // Solely to make the lazy kernel work
@ -2538,7 +2539,7 @@ namespace CommonKernelFunctors {
// 25 possibilities, so I keep the template. // 25 possibilities, so I keep the template.
template <class T1, class T2> 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 operator()(const T1& t1, const T2& t2) const
{ return internal::intersection(t1, t2, K()); } { return internal::intersection(t1, t2, K()); }
}; };
@ -2548,11 +2549,20 @@ namespace CommonKernelFunctors {
{ {
typedef typename K::Plane_3 Plane_3; typedef typename K::Plane_3 Plane_3;
public: public:
template<typename A, typename B> template<typename>
struct Result { struct result;
typedef typename Intersection_traits<K, A, B>::result_type Type;
// Boost MPL compatibility template<typename F, typename A, typename B>
typedef Type type; 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 // Solely to make the lazy kernel work
@ -2562,7 +2572,7 @@ namespace CommonKernelFunctors {
// n possibilities, so I keep the template. // n possibilities, so I keep the template.
template <class T1, class T2> 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 operator()(const T1& t1, const T2& t2) const
{ return internal::intersection(t1, t2, K() ); } { return internal::intersection(t1, t2, K() ); }