From d7cf32bcfaba6d2c9bc85bd067e9117e8d752bf2 Mon Sep 17 00:00:00 2001 From: Adam Wulkiewicz Date: Fri, 14 Dec 2012 14:49:45 +0000 Subject: [PATCH] Rtree value_type must no longer have default ctor defined. Added static_vector::assign(), added assertion in static_vector::resize(). Added test for value without default ctor.. [SVN r81940] --- .../extensions/index/rtree/rstar/insert.hpp | 45 ++++--- .../rtree/rstar/redistribute_elements.hpp | 6 +- .../geometry/extensions/index/rtree/rtree.hpp | 5 +- .../index/rtree/visitors/nearest_query.hpp | 7 +- .../extensions/index/static_vector.hpp | 45 ++++--- test/rtree/test_rtree.hpp | 116 ++++++++++++++++-- 6 files changed, 168 insertions(+), 56 deletions(-) diff --git a/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp b/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp index e7e7567c2..1d4e17f2e 100644 --- a/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp +++ b/include/boost/geometry/extensions/index/rtree/rstar/insert.hpp @@ -60,19 +60,22 @@ public: geometry::centroid(rtree::elements(*parent)[current_child_index].first, node_center); // fill the container of centers' distances of children from current node's center - typename index::detail::rtree::container_from_elements_type< + typedef typename index::detail::rtree::container_from_elements_type< elements_type, std::pair - >::type sorted_elements; + >::type sorted_elements_type; + sorted_elements_type sorted_elements; // If constructor is used instead of resize() MS implementation leaks here - sorted_elements.resize(elements_count); // MAY THROW, STRONG (V, E: alloc, copy) + sorted_elements.reserve(elements_count); // MAY THROW, STRONG (V, E: alloc, copy) - for ( size_t i = 0 ; i < elements_count ; ++i ) + for ( typename elements_type::const_iterator it = elements.begin() ; + it != elements.end() ; ++it ) { point_type element_center; - geometry::centroid( rtree::element_indexable(elements[i], translator), element_center); - sorted_elements[i].first = geometry::comparable_distance(node_center, element_center); - sorted_elements[i].second = elements[i]; // MAY THROW (V, E: copy) + geometry::centroid( rtree::element_indexable(*it, translator), element_center); + sorted_elements.push_back(std::make_pair( + geometry::comparable_distance(node_center, element_center), + *it)); // MAY THROW (V, E: copy) } // sort elements by distances from center @@ -83,24 +86,34 @@ public: distances_dsc); // MAY THROW, BASIC (V, E: copy) // copy elements which will be reinserted - result_elements.resize(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy) - for ( size_t i = 0 ; i < reinserted_elements_count ; ++i ) - result_elements[i] = sorted_elements[i].second; // MAY THROW (V, E: copy) + result_elements.clear(); + result_elements.reserve(reinserted_elements_count); // MAY THROW, STRONG (V, E: alloc, copy) + for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() ; + it != sorted_elements.begin() + reinserted_elements_count ; ++it ) + { + result_elements.push_back(it->second); // MAY THROW (V, E: copy) + } try { // copy remaining elements to the current node - size_t elements_new_count = elements_count - reinserted_elements_count; - elements.resize(elements_new_count); // SHOULDN'T THROW (new_size <= old size) - for ( size_t i = 0 ; i < elements_new_count ; ++i ) - elements[i] = sorted_elements[i + reinserted_elements_count].second; // MAY THROW (V, E: copy) + elements.clear(); + elements.reserve(elements_count - reinserted_elements_count); // SHOULDN'T THROW (new_size <= old size) + for ( typename sorted_elements_type::const_iterator it = sorted_elements.begin() + reinserted_elements_count; + it != sorted_elements.end() ; ++it ) + { + elements.push_back(it->second); // MAY THROW (V, E: copy) + } } catch(...) { elements.clear(); - for ( size_t i = 0 ; i < elements_count ; ++i ) - destroy_element::apply(sorted_elements[i].second, allocators); + for ( typename sorted_elements_type::iterator it = sorted_elements.begin() ; + it != sorted_elements.end() ; ++it ) + { + destroy_element::apply(it->second, allocators); + } throw; // RETHROW } diff --git a/include/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp b/include/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp index 06e212412..f90e7656b 100644 --- a/include/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp +++ b/include/boost/geometry/extensions/index/rtree/rstar/redistribute_elements.hpp @@ -382,10 +382,8 @@ struct redistribute_elements(elements1.begin(), elements1.end(), translator); diff --git a/include/boost/geometry/extensions/index/rtree/rtree.hpp b/include/boost/geometry/extensions/index/rtree/rtree.hpp index 876a6edf2..90ac2b5dd 100644 --- a/include/boost/geometry/extensions/index/rtree/rtree.hpp +++ b/include/boost/geometry/extensions/index/rtree/rtree.hpp @@ -873,7 +873,7 @@ private: point_type > result_type; - result_type result; + result_type result(v); detail::rtree::visitors::nearest_query< value_type, @@ -888,7 +888,8 @@ private: detail::rtree::apply_visitor(nearest_v, *m_root); - return result.get(v); + //return result.get(v); + return result.is_comparable_distance_valid() ? 1 : 0; } /*! diff --git a/include/boost/geometry/extensions/index/rtree/visitors/nearest_query.hpp b/include/boost/geometry/extensions/index/rtree/visitors/nearest_query.hpp index 54b81d8bf..5b52dac39 100644 --- a/include/boost/geometry/extensions/index/rtree/visitors/nearest_query.hpp +++ b/include/boost/geometry/extensions/index/rtree/visitors/nearest_query.hpp @@ -33,8 +33,9 @@ public: typename translator::indexable_type::type >::type distance_type; - inline nearest_query_result_one() - : m_comp_dist((std::numeric_limits::max)()) + inline nearest_query_result_one(Value & value) + : m_value(value) + , m_comp_dist((std::numeric_limits::max)()) {} inline void store(Value const& val, distance_type const& curr_comp_dist) @@ -63,7 +64,7 @@ public: } private: - Value m_value; + Value & m_value; distance_type m_comp_dist; }; diff --git a/include/boost/geometry/extensions/index/static_vector.hpp b/include/boost/geometry/extensions/index/static_vector.hpp index 5796ef6a6..b5f60d7eb 100644 --- a/include/boost/geometry/extensions/index/static_vector.hpp +++ b/include/boost/geometry/extensions/index/static_vector.hpp @@ -73,24 +73,7 @@ public: { //BOOST_ASSERT_MSG(other.m_size <= Capacity, "capacity too small"); - if ( m_size <= other.m_size ) - { - this->copy(other.ptr(0), other.ptr(m_size), this->ptr(0), - boost::has_trivial_assign()); // may throw - - this->uninitialized_copy(other.ptr(m_size), other.ptr(other.m_size), this->ptr(m_size), - boost::has_trivial_copy()); // may throw - m_size = other.m_size; - } - else - { - this->copy(other.ptr(0), other.ptr(other.m_size), this->ptr(0), - boost::has_trivial_assign()); // may throw - - this->destroy(this->ptr(other.m_size), this->ptr(m_size), - boost::has_trivial_destructor()); - m_size = other.m_size; - } + this->assign(other->ptr(0), other->ptr(other.m_size)); return *this; } @@ -113,6 +96,7 @@ public: } else { + BOOST_ASSERT_MSG(s <= Capacity, "size can't exceed the capacity"); this->uninitialized_fill(this->ptr(m_size), this->ptr(s), value); // may throw m_size = s; } @@ -143,6 +127,31 @@ public: this->destroy(this->ptr(m_size), boost::has_trivial_destructor()); } + // basic + void assign(const value_type * first, const value_type * last) + { + size_type s = std::distance(first, last); + + if ( m_size <= s ) + { + this->copy(first, first + m_size, this->ptr(0), + boost::has_trivial_assign()); // may throw + + this->uninitialized_copy(first + m_size, last, this->ptr(m_size), + boost::has_trivial_copy()); // may throw + m_size = s; + } + else + { + this->copy(first, last, this->ptr(0), + boost::has_trivial_assign()); // may throw + + this->destroy(this->ptr(s), this->ptr(m_size), + boost::has_trivial_destructor()); + m_size = s; + } + } + // nothrow void clear() { diff --git a/test/rtree/test_rtree.hpp b/test/rtree/test_rtree.hpp index 4c5f6dc89..0281fd4b2 100644 --- a/test/rtree/test_rtree.hpp +++ b/test/rtree/test_rtree.hpp @@ -50,6 +50,14 @@ struct generate_outside_point< bg::model::point > } }; +// Default value generation + +template +struct generate_value_default +{ + static Value apply(){ return Value(); } +}; + // Values, input and rtree generation template @@ -225,10 +233,11 @@ struct generate_value< boost::shared_ptr > { typedef bg::model::point P; typedef test_object

O; + typedef boost::shared_ptr R; - static boost::shared_ptr apply(int x, int y) + static R apply(int x, int y) { - return boost::shared_ptr(new O(P(x, y))); + return R(new O(P(x, y))); } }; @@ -237,10 +246,11 @@ struct generate_value< boost::shared_ptr > { typedef bg::model::point P; typedef test_object

O; + typedef boost::shared_ptr R; - static boost::shared_ptr apply(int x, int y, int z) + static R apply(int x, int y, int z) { - return boost::shared_ptr(new O(P(x, y, z))); + return R(new O(P(x, y, z))); } }; @@ -283,14 +293,16 @@ template struct generate_value< counting_value > > { typedef bg::model::point P; - static counting_value

apply(int x, int y) { return counting_value

(P(x, y)); } + typedef counting_value

R; + static R apply(int x, int y) { return R(P(x, y)); } }; template struct generate_value< counting_value > > { typedef bg::model::point P; - static counting_value

apply(int x, int y, int z) { return counting_value

(P(x, y, z)); } + typedef counting_value

R; + static R apply(int x, int y, int z) { return R(P(x, y, z)); } }; template @@ -298,7 +310,8 @@ struct generate_value< counting_value > { typedef bg::model::point P; typedef bg::model::box

B; - static counting_value apply(int x, int y) { return counting_value(B(P(x, y), P(x+2, y+3))); } + typedef counting_value R; + static R apply(int x, int y) { return R(B(P(x, y), P(x+2, y+3))); } }; template @@ -306,7 +319,78 @@ struct generate_value< counting_value > { typedef bg::model::point P; typedef bg::model::box

B; - static counting_value apply(int x, int y, int z) { return counting_value(B(P(x, y, z), P(x+2, y+3, z+4))); } + typedef counting_value R; + static R apply(int x, int y, int z) { return R(B(P(x, y, z), P(x+2, y+3, z+4))); } +}; + +// value without default constructor + +template +struct value_no_dctor +{ + value_no_dctor(Indexable const& i) : indexable(i) {} + Indexable indexable; +}; + +namespace boost { namespace geometry { namespace index { namespace translator { + + template + struct def< value_no_dctor > + { + typedef value_no_dctor value_type; + typedef Indexable const& result_type; + + result_type operator()(value_type const& value) const + { + return value.indexable; + } + + bool equals(value_type const& v1, value_type const& v2) const + { + return boost::geometry::equals(v1.indexable, v2.indexable); + } + }; + +}}}} + +template +struct generate_value_default< value_no_dctor > +{ + static value_no_dctor apply() { return value_no_dctor(Indexable()); } +}; + +template +struct generate_value< value_no_dctor > > +{ + typedef bg::model::point P; + typedef value_no_dctor

R; + static R apply(int x, int y) { return R(P(x, y)); } +}; + +template +struct generate_value< value_no_dctor > > +{ + typedef bg::model::point P; + typedef value_no_dctor

R; + static R apply(int x, int y, int z) { return R(P(x, y, z)); } +}; + +template +struct generate_value< value_no_dctor > > > +{ + typedef bg::model::point P; + typedef bg::model::box

B; + typedef value_no_dctor R; + static R apply(int x, int y) { return R(B(P(x, y), P(x+2, y+3))); } +}; + +template +struct generate_value< value_no_dctor > > > +{ + typedef bg::model::point P; + typedef bg::model::box

B; + typedef value_no_dctor R; + static R apply(int x, int y, int z) { return R(B(P(x, y, z), P(x+2, y+3, z+4))); } }; // generate input @@ -625,7 +709,7 @@ void test_nearest_query(Rtree const& rtree, std::vector const& input, Poi typedef typename bg::default_distance_result::type D; D smallest_d = (std::numeric_limits::max)(); - Value expected_output; + Value expected_output(generate_value_default::apply()); BOOST_FOREACH(Value const& v, input) { D d = bgi::comparable_distance_near(pt, rtree.translator()(v)); @@ -637,7 +721,7 @@ void test_nearest_query(Rtree const& rtree, std::vector const& input, Poi } size_t n = ( (std::numeric_limits::max)() == smallest_d ) ? 0 : 1; - Value output; + Value output(generate_value_default::apply()); size_t n_res = rtree.nearest_query(pt, output); BOOST_CHECK(n == n_res); @@ -711,7 +795,7 @@ void test_nearest_query_k(Rtree const& rtree, std::vector const& input, P biggest_d = test_output.back().first; // transform test output to vector of values - std::vector expected_output(test_output.size()); + std::vector expected_output(test_output.size(), generate_value_default::apply()); std::transform(test_output.begin(), test_output.end(), expected_output.begin(), TestNearestKTransform()); // calculate output using rtree @@ -744,11 +828,12 @@ void test_nearest_query_k(Rtree const& rtree, std::vector const& input, P template void test_nearest_query_not_found(Rtree const& rtree, Point const& pt, CoordinateType max_distance_1, CoordinateType max_distance_k) { - typename Rtree::value_type output; + typedef typename Rtree::value_type Value; + Value output(generate_value_default::apply()); size_t n_res = rtree.nearest_query(bgi::max_bounded(pt, max_distance_1), output); BOOST_CHECK(0 == n_res); - std::vector output_v; + std::vector output_v; n_res = rtree.nearest_query(bgi::max_bounded(pt, max_distance_k), 5, std::back_inserter(output_v)); BOOST_CHECK(output_v.size() == n_res); BOOST_CHECK(n_res < 5); @@ -1159,12 +1244,14 @@ void test_rtree_for_point(Parameters const& parameters = Parameters()) typedef std::pair PairP; typedef boost::tuple TupleP; typedef boost::shared_ptr< test_object > SharedPtrP; + typedef value_no_dctor VNoDCtor; test_rtree_by_value(parameters); test_rtree_by_value(parameters); test_rtree_by_value(parameters); test_rtree_by_value(parameters); + test_rtree_by_value(parameters); test_count_rtree_values(parameters); } @@ -1175,11 +1262,14 @@ void test_rtree_for_box(Parameters const& parameters = Parameters()) typedef bg::model::box Box; typedef std::pair PairB; typedef boost::tuple TupleB; + typedef value_no_dctor VNoDCtor; test_rtree_by_value(parameters); test_rtree_by_value(parameters); test_rtree_by_value(parameters); + test_rtree_by_value(parameters); + test_count_rtree_values(parameters); }