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/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); \

View File

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

View File

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

View File

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

View File

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

View File

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