From 027de166f401fdc5ba6c04ac65f75ba4493eb400 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 26 Aug 2019 15:42:24 +0200 Subject: [PATCH 1/2] Make it possible for Search_traits_adapter to work without lvalue point map --- .../include/CGAL/Search_traits_adapter.h | 131 +++++++++++++++++- 1 file changed, 125 insertions(+), 6 deletions(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 1fc87b33290..2e2039fc172 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -34,6 +34,7 @@ #include #include #include +#include namespace CGAL{ @@ -78,9 +79,6 @@ template class Search_traits_adapter : public Base_traits{ PointPropertyMap ppmap; - CGAL_static_assertion( ( boost::is_same< boost::lvalue_property_map_tag, - typename boost::property_traits::category - >::value ) ); public: typedef Base_traits Base; typedef typename internal::Get_iso_box_d::type Iso_box_d; @@ -89,17 +87,19 @@ public: const Base_traits& base=Base_traits() ):Base_traits(base),ppmap(ppmap_){} - typedef typename Base_traits::Cartesian_const_iterator_d Cartesian_const_iterator_d; + typedef Point_with_info Point_d; typedef typename Base_traits::FT FT; typedef typename Base_traits::Dimension Dimension; - struct Construct_cartesian_const_iterator_d: public Base_traits::Construct_cartesian_const_iterator_d{ + // Default if point map is lvalue: use Construct_cartesian_const_iterator_d + struct Construct_cartesian_const_iterator_d_lvalue: public Base_traits::Construct_cartesian_const_iterator_d{ PointPropertyMap ppmap; typedef typename Base_traits::Construct_cartesian_const_iterator_d Base; - Construct_cartesian_const_iterator_d(const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) + Construct_cartesian_const_iterator_d_lvalue + (const typename Base_traits::Construct_cartesian_const_iterator_d& base, const PointPropertyMap& ppmap_) :Base_traits::Construct_cartesian_const_iterator_d(base), ppmap(ppmap_){} typename Base_traits::Cartesian_const_iterator_d operator()(const Point_with_info& p) const @@ -132,6 +132,125 @@ public: { return Base::operator() (p,0); } }; + // If point map is not lvalue, use this work-around that stores a + // Point object in a shared pointer to avoid iterating on a temp + // object + class No_lvalue_iterator + : public boost::iterator_facade::value_type, + std::random_access_iterator_tag + > + { + typedef boost::iterator_facade::value_type, + std::random_access_iterator_tag + > Facade; + + typedef typename std::iterator_traits::value_type + Dereference_type; + typedef typename boost::property_traits::value_type + Point; + + boost::shared_ptr point; + std::size_t idx; + + public: + + No_lvalue_iterator() : point(NULL), idx(0) { } + No_lvalue_iterator(const Point& point, std::size_t idx = 0) : point(new Point(point)), idx(idx) { } + + private: + + friend class boost::iterator_core_access; + void increment() + { + ++idx; + CGAL_assertion(point != boost::shared_ptr()); + } + void decrement() + { + --idx; + CGAL_assertion(point != boost::shared_ptr()); + } + + void advance(std::ptrdiff_t n) + { + idx += n; + CGAL_assertion(point != boost::shared_ptr()); + } + + std::ptrdiff_t distance_to(const No_lvalue_iterator& other) const + { + return other.idx - this->idx; + + } + bool equal(const No_lvalue_iterator& other) const + { + return this->idx == other.idx; + } + + Dereference_type& + dereference() const { return const_cast((*point)[idx]); } + + }; + + // Alternative Construct_cartesian_const_iterator_d if the point map + // is not lvalue (generates No_lvalue_iterator objects) + struct Construct_cartesian_const_iterator_d_no_lvalue { + typedef No_lvalue_iterator result_type; + PointPropertyMap ppmap; + + Construct_cartesian_const_iterator_d_no_lvalue + (const typename Base_traits::Construct_cartesian_const_iterator_d&, const PointPropertyMap& ppmap_) + : ppmap(ppmap_) { } + + No_lvalue_iterator operator()(const Point_with_info& p) const + { return No_lvalue_iterator(get(ppmap, p)); } + + No_lvalue_iterator operator()(const Point_with_info& p, int) const + { return No_lvalue_iterator(get(ppmap, p),0); } + + // These 2 additional operators forward the call to Base_traits. + // This is needed because of an undocumented requirement of + // Orthogonal_k_neighbor_search and Orthogonal_incremental_neighbor_search: + // Traits::Construct_cartesian_const_iterator should be callable + // on the query point type. If the query point type is the same as + // Point_with_info, we disable it. + + template // boost::disable_if requires a template argument to work + No_lvalue_iterator operator()(const Point& p, + typename boost::disable_if< + boost::is_same >::type* = 0 + ) const + { return No_lvalue_iterator(p); } + + template // boost::disable_if requires a template argument to work + No_lvalue_iterator operator()(const Point& p, int, + typename boost::disable_if< + boost::is_same >::type* = 0 + ) const + { return No_lvalue_iterator(p,0); } + }; + + // Select type of iterator + construct class depending on whether + // point map is lvalue or not + typedef typename boost::mpl::if_ + ::category >, + typename Base::Cartesian_const_iterator_d, + No_lvalue_iterator>::type + Cartesian_const_iterator_d; + typedef typename boost::mpl::if_ + ::category >, + Construct_cartesian_const_iterator_d_lvalue, + Construct_cartesian_const_iterator_d_no_lvalue>::type + Construct_cartesian_const_iterator_d; + struct Construct_iso_box_d: public Base::Construct_iso_box_d{ PointPropertyMap ppmap; typedef typename Base_traits::FT FT; // needed for VC++, because otherwise it is taken from the private typedef of the base class From 33cc6f048359a4e0e661bcc2c0b6fe57d2ab9932 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 26 Aug 2019 15:43:02 +0200 Subject: [PATCH 2/2] Update doc of Search_traits_adapter --- .../doc/Spatial_searching/CGAL/Search_traits_adapter.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Search_traits_adapter.h b/Spatial_searching/doc/Spatial_searching/CGAL/Search_traits_adapter.h index f7a9ea9b19e..005201d8d74 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Search_traits_adapter.h @@ -11,7 +11,7 @@ in a nearest neighbor search algorithm, this class must be used as distance. \tparam Key is a type that is associated to a point of type `Base_distance::Point_d`. -\tparam PointPropertyMap is a model of `LvaluePropertyMap` +\tparam PointPropertyMap is a model of `ReadablePropertyMap` with `Key` as key type and `Base_distance::Point_d` as value type. \tparam Base_distance is a model of either `GeneralDistance` or `OrthogonalDistance`.