// 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_CONVERTER_H #define CGAL_KERNEL_D_CARTESIAN_CONVERTER_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace CGAL { namespace internal { // Reverses order, but that shouldn't matter. template struct Map_taglist_to_typelist : Map_taglist_to_typelist::type ::template add::type> {}; template struct Map_taglist_to_typelist > : typeset<> {}; } template > struct Object_converter { typedef Object result_type; template result_type operator()(Object const& o, F const& f) const { typedef typename List::head H; if (H const* ptr = object_cast(&o)) return make_object(f(*ptr)); else return Object_converter()(o,f); } }; template<> struct Object_converter > { typedef Object result_type; template result_type operator()(Object const&,F const&)const { CGAL_error_msg("Cartesiand_converter is unable to determine what is wrapped in the Object"); return Object(); } }; //TODO: special case when K1==K2 (or they are very close?) template class KernelD_converter_ : public KernelD_converter_ { typedef typename List::head Tag_; typedef typename List::tail Rest; typedef KernelD_converter_ Base; typedef typename Get_type::type K1_Obj; typedef typename Get_type::type K2_Obj; typedef typename Get_functor >::type K1_Conv; typedef KO_converter KOC; typedef CGAL_BOOSTD is_same no_converter; typedef typename internal::Map_taglist_to_typelist::type::template contains duplicate; // Disable the conversion in some cases: struct Do_not_use{}; // Explicit calls to boost::mpl functions to avoid parenthesis // warning on some versions of GCC typedef typename boost::mpl::if_ < // If Point==Vector, keep only one conversion boost::mpl::or_, // For iterator objects, the default is make_transforming_iterator boost::mpl::bool_<(iterator_tag_traits::is_iterator && no_converter::value)> >, Do_not_use,K1_Obj>::type argument_type; //typedef typename KOC::argument_type K1_Obj; //typedef typename KOC::result_type K2_Obj; public: using Base::operator(); // don't use directly, just make it accessible to the next level K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD true_type)const{ return KOC()(this->myself().kernel(),this->myself().kernel2(),this->myself(),o); } K2_Obj helper(K1_Obj const& o,CGAL_BOOSTD false_type)const{ return K1_Conv(this->myself().kernel())(this->myself().kernel2(),this->myself(),o); } K2_Obj operator()(argument_type const& o)const{ return helper(o,no_converter()); } template struct result:Base::template result{}; template struct result {typedef K2_Obj type;}; }; template class KernelD_converter_ > { public: struct Do_not_use2{}; void operator()(Do_not_use2)const{} template struct result; Final_& myself(){return *static_cast(this);} Final_ const& myself()const{return *static_cast(this);} }; // TODO: use the intersection of Kn::Object_list. template::type //typeset::add::type/*::add::type*/ > class KernelD_converter : public Store_kernel, public Store_kernel2, public KernelD_converter_,K1,K2,List_> { typedef KernelD_converter Self; typedef Self Final_; typedef KernelD_converter_ Base; typedef typename Get_type::type FT1; typedef typename Get_type::type FT2; typedef NT_converter NTc; NTc c; // TODO: compressed storage as this is likely empty and the converter gets passed around (and stored in iterators) public: KernelD_converter(){} KernelD_converter(K1 const&a,K2 const&b):Store_kernel(a),Store_kernel2(b){} // For boost::result_of, used in transforming_iterator template::value?42:0> struct result:Base::template result{}; template struct result { typedef transforming_iterator type; }; template struct result{typedef K2 type;}; template struct result{typedef int type;}; // Ideally the next 2 would come with Point_tag and Vector_tag, but that's hard... template struct result{typedef Origin type;}; template struct result{typedef Null_vector type;}; template struct result{typedef Object type;}; template struct result{typedef FT2 type;}; using Base::operator(); typename Store_kernel2::reference2_type operator()(K1 const&)const{return this->kernel2();} int operator()(int i)const{return i;} Origin operator()(Origin const&o)const{return o;} Null_vector operator()(Null_vector const&v)const{return v;} FT2 operator()(FT1 const&x)const{return c(x);} //RT2 operator()(typename First_if_different::Type const&x)const{return cr(x);} typename Get_type::type const& operator()(typename Get_type::type const&o)const { return o; } // Both kernels should have the same, returning a reference should warn if not. template transforming_iterator,It>::type> operator()(It const& it) const { return make_transforming_iterator(it,*this); } template //TODO: use decltype in C++11 instead of result std::vector::type> operator()(const std::vector& v) const { return std::vector::type>(operator()(v.begin()),operator()(v.begin())); } //TODO: convert std::list and other containers? Object operator()(const Object &obj) const { typedef typename internal::Map_taglist_to_typelist::type Possibilities; //TODO: add Empty, vector, etc to the list. return Object_converter()(obj,*this); } //TODO: convert boost::variant }; } //namespace CGAL #endif // CGAL_KERNEL_D_CARTESIAN_CONVERTER_H