diff --git a/include/boost/geometry/util/range.hpp b/include/boost/geometry/util/range.hpp index ddee14ea8..949d99df9 100644 --- a/include/boost/geometry/util/range.hpp +++ b/include/boost/geometry/util/range.hpp @@ -162,7 +162,7 @@ inline void pop_back(Range & rng) /*! \brief Short utility to conveniently remove an element from a mutable range. - It uses std::copy() and resize(). It requires mutable iterator as parameter. + It uses std::copy() and resize(). Version taking mutable iterators. \ingroup utility */ template @@ -184,9 +184,31 @@ erase(Range & rng, return it; } +/*! +\brief Short utility to conveniently remove an element from a mutable range. + It uses std::copy() and resize(). Version taking non-mutable iterators. +\ingroup utility +*/ +template +inline typename boost::range_iterator::type +erase(Range & rng, + typename boost::range_iterator::type cit) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept )); + + typename boost::range_iterator::type + it = boost::begin(rng) + + std::distance(boost::const_begin(rng), cit); + + erase(rng, it); + + // NOTE: assuming that resize() doesn't invalidate the iterators + return cit; +} + /*! \brief Short utility to conveniently remove a range of elements from a mutable range. - It uses std::copy() and resize(). It requires mutable iterators as parameters. + It uses std::copy() and resize(). Version taking mutable iterators. \ingroup utility */ template @@ -214,6 +236,32 @@ erase(Range & rng, return first; } +/*! +\brief Short utility to conveniently remove a range of elements from a mutable range. + It uses std::copy() and resize(). Version taking non-mutable iterators. +\ingroup utility +*/ +template +inline typename boost::range_iterator::type +erase(Range & rng, + typename boost::range_iterator::type cfirst, + typename boost::range_iterator::type clast) +{ + BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept )); + + typename boost::range_iterator::type + first = boost::begin(rng) + + std::distance(boost::const_begin(rng), cfirst); + typename boost::range_iterator::type + last = boost::begin(rng) + + std::distance(boost::const_begin(rng), clast); + + erase(rng, first, last); + + // NOTE: assuming that resize() doesn't invalidate the iterators + return cfirst; +} + }}} // namespace boost::geometry::range #endif // BOOST_GEOMETRY_UTIL_RANGE_HPP diff --git a/test/util/range.cpp b/test/util/range.cpp index 0e2530b79..579c59f57 100644 --- a/test/util/range.cpp +++ b/test/util/range.cpp @@ -15,10 +15,60 @@ #include #include -int test_main(int, char* []) +namespace bgt { + +template +struct beginner +{ + template + typename boost::range_iterator::type + operator()(Range & rng) + { + return boost::begin(rng); + } +}; +template <> +struct beginner +{ + template + typename boost::range_iterator::type + operator()(Range & rng) + { + return boost::const_begin(rng); + } +}; + +template +struct ender +{ + template + typename boost::range_iterator::type + operator()(Range & rng) + { + return boost::end(rng); + } +}; +template <> +struct ender +{ + template + typename boost::range_iterator::type + operator()(Range & rng) + { + return boost::const_end(rng); + } +}; + +} // namespace bgt + +template +void test_all() { namespace bgr = bg::range; + bgt::beginner begin; + bgt::ender end; + std::vector v; for (int i = 0 ; i < 20 ; ++i) { @@ -42,46 +92,52 @@ int test_main(int, char* []) BOOST_CHECK(boost::size(v) == 14); // [0,13] BOOST_CHECK(bgr::back(v) == 13); - bgr::erase(v, boost::end(v) - 1); + bgr::erase(v, end(v) - 1); BOOST_CHECK(boost::size(v) == 13); // [0,12] BOOST_CHECK(bgr::back(v) == 12); - bgr::erase(v, boost::end(v) - 3, boost::end(v)); + bgr::erase(v, end(v) - 3, end(v)); BOOST_CHECK(boost::size(v) == 10); // [0,9] BOOST_CHECK(bgr::back(v) == 9); - bgr::erase(v, boost::begin(v) + 2); + bgr::erase(v, begin(v) + 2); BOOST_CHECK(boost::size(v) == 9); // {0,1,3..9} BOOST_CHECK(bgr::at(v, 1) == 1); BOOST_CHECK(bgr::at(v, 2) == 3); BOOST_CHECK(bgr::back(v) == 9); - bgr::erase(v, boost::begin(v) + 2, boost::begin(v) + 2); + bgr::erase(v, begin(v) + 2, begin(v) + 2); BOOST_CHECK(boost::size(v) == 9); // {0,1,3..9} BOOST_CHECK(bgr::at(v, 1) == 1); BOOST_CHECK(bgr::at(v, 2) == 3); BOOST_CHECK(bgr::back(v) == 9); - bgr::erase(v, boost::begin(v) + 2, boost::begin(v) + 5); + bgr::erase(v, begin(v) + 2, begin(v) + 5); BOOST_CHECK(boost::size(v) == 6); // {0,1,6..9} BOOST_CHECK(bgr::at(v, 1) == 1); BOOST_CHECK(bgr::at(v, 2) == 6); BOOST_CHECK(bgr::back(v) == 9); - bgr::erase(v, boost::begin(v)); + bgr::erase(v, begin(v)); BOOST_CHECK(boost::size(v) == 5); // {1,6..9} BOOST_CHECK(bgr::at(v, 0) == 1); BOOST_CHECK(bgr::at(v, 1) == 6); BOOST_CHECK(bgr::back(v) == 9); - bgr::erase(v, boost::begin(v), boost::begin(v) + 3); + bgr::erase(v, begin(v), begin(v) + 3); BOOST_CHECK(boost::size(v) == 2); // {8,9} BOOST_CHECK(bgr::at(v, 0) == 8); BOOST_CHECK(bgr::at(v, 1) == 9); BOOST_CHECK(bgr::back(v) == 9); - bgr::erase(v, boost::begin(v), boost::end(v)); + bgr::erase(v, begin(v), end(v)); BOOST_CHECK(boost::size(v) == 0); +} + +int test_main(int, char* []) +{ + test_all(); + test_all(); return 0; }