#ifndef CGAL_KERNEL_D_CARTESIAN_WRAP_H #define CGAL_KERNEL_D_CARTESIAN_WRAP_H #include #include #include #include #include #include #include #include #include #include //TODO: do we want to store the kernel ref in the Object wrappers? It would allow for additions and operator[] and things like that to work, but objects would still need to be created by functors. namespace CGAL { namespace internal { BOOST_MPL_HAS_XXX_TRAIT_DEF(Is_wrapper) template::value> struct Is_wrapper { enum { value=false }; typedef Tag_false type; }; template struct Is_wrapper { typedef typename T::Is_wrapper type; enum { value=type::value }; }; template::value> struct Is_wrapper_iterator { enum { value=false }; typedef Tag_false type; }; template struct Is_wrapper_iterator : Is_wrapper::value_type> { }; struct Forward_rep { //TODO: make a good C++0X version with perfect forwarding //#ifdef CGAL_CXX0X //template ::type>::value&&!Is_wrapper_iterator::type>::value>::type> //T&& operator()(typename std::remove_reference::type&& t) const {return static_cast(t);}; //template ::type>::value&&!Is_wrapper_iterator::type>::value>::type> //T&& operator()(typename std::remove_reference::type& t) const {return static_cast(t);}; // //template ::type>::value>::type> //typename Type_copy_cvref::type::Rep>::type&& //operator()(T&& t) const { // return static_cast::type::Rep>::type&&>(t.rep()); //}; // //template ::type>::value>::type> //transforming_iterator::type> //operator()(T&& t) const { // return make_transforming_iterator(std::forward(t),Forward_rep()); //}; //#else template ::value,bool=Is_wrapper_iterator::value> struct result_; template struct result_{typedef T const& type;}; template struct result_{typedef typename decay::type::Rep const& type;}; template struct result_{typedef transforming_iterator::type> type;}; template struct result; template struct result : result_ {}; template typename boost::disable_if,Is_wrapper_iterator >,T>::type const& operator()(T const& t) const {return t;} template typename boost::enable_if,T>::type::Rep const& operator()(T const& t) const {return t.rep();} template transforming_iterator,T>::type> operator()(T const& t) const {return make_transforming_iterator(t,Forward_rep());} //#endif }; } template ::value> struct Map_wrapping_type : Get_type {}; #define CGAL_REGISTER_OBJECT_WRAPPER(X) \ template \ struct Map_wrapping_type { \ typedef X##_d type; \ } CGAL_REGISTER_OBJECT_WRAPPER(Point); CGAL_REGISTER_OBJECT_WRAPPER(Vector); CGAL_REGISTER_OBJECT_WRAPPER(Segment); CGAL_REGISTER_OBJECT_WRAPPER(Sphere); #undef CGAL_REGISTER_OBJECT_WRAPPER // Note: this tends to be an all or nothing thing currently, wrapping // only some types breaks, probably because we don't check whether the // return type is indeed wrapped. template < typename Base_ , typename Derived_ = Default > struct Cartesian_wrap : public Base_ { CGAL_CONSTEXPR Cartesian_wrap(){} CGAL_CONSTEXPR Cartesian_wrap(int d):Base_(d){} typedef Base_ Kernel_base; typedef Cartesian_wrap Self; typedef typename Default::Get::type Derived; // FIXME: The list doesn't belong here. typedef boost::mpl::vector Wrapped_list; template struct Type : Map_wrapping_type {}; //Translate the arguments template ::type, bool=Provides_functor::value, bool=boost::mpl::contains::type>::type::value> struct Functor { typedef typename Get_functor::type B; struct type { B b; type(){} type(Self const&k):b(k){} typedef typename B::result_type result_type; #ifdef CGAL_CXX0X template result_type operator()(U&&...u)const{ return b(internal::Forward_rep()(u)...); } #else #define VAR(Z,N,_) internal::Forward_rep()(u##N) #define CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ return b(BOOST_PP_ENUM(N,VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CODE,_) #undef CODE #undef VAR #endif }; }; // Preserve the difference between Null_functor and nothing. template struct Functor : Get_functor {}; //Translate both the arguments and the result //TODO: Check Is_wrapper instead of relying on map_result_tag? template struct Functor { typedef typename Get_functor::type B; struct type { B b; type(){} type(Self const&k):b(k){} typedef typename map_result_tag::type result_tag; // FIXME: Self or Derived? typedef typename Get_type::type result_type; #ifdef CGAL_CXX0X template result_type operator()(U&&...u)const{ return result_type(Eval_functor(),b,internal::Forward_rep()(u)...); } #else #define VAR(Z,N,_) internal::Forward_rep()(u##N) #define CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ return result_type(Eval_functor(),b,BOOST_PP_ENUM(N,VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CODE,_) #undef CODE #undef VAR #endif }; }; }; template < typename Base_ > struct Cartesian_refcount : public Base_ { CGAL_CONSTEXPR Cartesian_refcount(){} CGAL_CONSTEXPR Cartesian_refcount(int d):Base_(d){} typedef Base_ Kernel_base; typedef Cartesian_refcount Self; // FIXME: Use object_list, or a list passed as argument, or anything // automatic. template struct Type : Get_type {}; #define CGAL_Kernel_obj(X,Y) \ template struct Type { typedef Ref_count_obj type; }; CGAL_Kernel_obj(Point,point) CGAL_Kernel_obj(Vector,vector) #undef CGAL_Kernel_obj template struct Dispatch { //typedef typename map_functor_type::type f_t; typedef typename map_result_tag::type r_t; enum { is_nul = boost::is_same::type,Null_functor>::value, ret_rcobj = boost::is_same::value || boost::is_same::value }; }; //Translate the arguments template::is_nul,bool=Dispatch::ret_rcobj> struct Functor { typedef typename Get_functor::type B; struct type { B b; type(){} type(Self const&k):b(k){} typedef typename B::result_type result_type; #ifdef CGAL_CXX0X template result_type operator()(U&&...u)const{ return b(internal::Forward_rep()(u)...); } #else result_type operator()()const{ return b(); } #define VAR(Z,N,_) internal::Forward_rep()(u##N) #define CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ return b(BOOST_PP_ENUM(N,VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CODE,_) #undef CODE #undef VAR #endif }; }; //Translate both the arguments and the result template struct Functor { typedef Null_functor type; }; template struct Functor { typedef typename Get_functor::type B; struct type { B b; type(){} type(Self const&k):b(k){} typedef typename map_result_tag::type result_tag; typedef typename Get_type::type result_type; #ifdef CGAL_CXX0X template result_type operator()(U&&...u)const{ return result_type(Eval_functor(),b,internal::Forward_rep()(u)...); } #else result_type operator()()const{ return result_type(Eval_functor(),b); } #define VAR(Z,N,_) internal::Forward_rep()(u##N) #define CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ return result_type(Eval_functor(),b,BOOST_PP_ENUM(N,VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CODE,_) #undef CODE #undef VAR #endif }; }; }; } //namespace CGAL #endif // CGAL_KERNEL_D_CARTESIAN_WRAP_H