// Copyright (c) 2014 // INRIA Saclay-Ile de France (France) // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // Author(s) : Marc Glisse #ifndef CGAL_KERNEL_D_CARTESIAN_WRAP_H #define CGAL_KERNEL_D_CARTESIAN_WRAP_H #include #include #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable:4003) // not enough actual parameters for macro 'BOOST_PP_EXPAND_I' // http://lists.boost.org/boost-users/2014/11/83291.php #endif #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::type>::value_type> { }; struct Forward_rep { //TODO: make a good C++0X version with perfect forwarding //#ifdef CGAL_CXX11 //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::disable_if,Is_wrapper_iterator >,T>::type& operator()(T& t) const {return t;} template typename T::Rep const& operator()(T const& t, typename boost::enable_if >::type* = 0) 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 Wrap::X##_d type; \ } CGAL_REGISTER_OBJECT_WRAPPER(Point); CGAL_REGISTER_OBJECT_WRAPPER(Vector); CGAL_REGISTER_OBJECT_WRAPPER(Segment); CGAL_REGISTER_OBJECT_WRAPPER(Sphere); CGAL_REGISTER_OBJECT_WRAPPER(Hyperplane); CGAL_REGISTER_OBJECT_WRAPPER(Weighted_point); #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; // TODO: pass the 2 types Self and Derived to the wrappers, they can use Self for most purposes and Derived only for Kernel_traits' typedef R. 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_CXX11 template result_type operator()(U&&...u)const{ return b(internal::Forward_rep()(u)...); } #else #define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) #define CGAL_CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ return b(BOOST_PP_ENUM(N,CGAL_VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) #undef CGAL_CODE #undef CGAL_VAR // In case the last argument needs to be non-const. Fragile... #define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) #define CGAL_CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u),V&v)const{ \ return b(BOOST_PP_ENUM(N,CGAL_VAR,),internal::Forward_rep()(v)); \ } BOOST_PP_REPEAT_FROM_TO(1,8,CGAL_CODE,_) #undef CGAL_CODE #undef CGAL_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_CXX11 template result_type operator()(U&&...u)const{ return result_type(Eval_functor(),b,internal::Forward_rep()(u)...); } #else #define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) #define CGAL_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,CGAL_VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) #undef CGAL_CODE #undef CGAL_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_CXX11 template result_type operator()(U&&...u)const{ return b(internal::Forward_rep()(u)...); } #else result_type operator()()const{ return b(); } #define CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) #define CGAL_CODE(Z,N,_) template result_type \ operator()(BOOST_PP_ENUM_BINARY_PARAMS(N,U,const&u))const{ \ return b(BOOST_PP_ENUM(N,CGAL_VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) #undef CGAL_CODE #undef CGAL_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_CXX11 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 CGAL_VAR(Z,N,_) internal::Forward_rep()(u##N) #define CGAL_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,CGAL_VAR,)); \ } BOOST_PP_REPEAT_FROM_TO(1,11,CGAL_CODE,_) #undef CGAL_CODE #undef CGAL_VAR #endif }; }; }; } //namespace CGAL #if defined(BOOST_MSVC) # pragma warning(pop) #endif #endif // CGAL_KERNEL_D_CARTESIAN_WRAP_H