[range] Add erase() taking non-mutable iterators (in-line with C++11 std::vector) + tests.

This commit is contained in:
Adam Wulkiewicz 2014-06-19 02:40:39 +02:00
parent 493f51f1fd
commit 43d0ef60f3
2 changed files with 115 additions and 11 deletions

View File

@ -162,7 +162,7 @@ inline void pop_back(Range & rng)
/*! /*!
\brief Short utility to conveniently remove an element from a mutable range. \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 \ingroup utility
*/ */
template <typename Range> template <typename Range>
@ -184,9 +184,31 @@ erase(Range & rng,
return it; 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 <typename Range>
inline typename boost::range_iterator<Range const>::type
erase(Range & rng,
typename boost::range_iterator<Range const>::type cit)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
typename boost::range_iterator<Range>::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. \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 \ingroup utility
*/ */
template <typename Range> template <typename Range>
@ -214,6 +236,32 @@ erase(Range & rng,
return first; 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 <typename Range>
inline typename boost::range_iterator<Range const>::type
erase(Range & rng,
typename boost::range_iterator<Range const>::type cfirst,
typename boost::range_iterator<Range const>::type clast)
{
BOOST_RANGE_CONCEPT_ASSERT(( boost::RandomAccessRangeConcept<Range> ));
typename boost::range_iterator<Range>::type
first = boost::begin(rng)
+ std::distance(boost::const_begin(rng), cfirst);
typename boost::range_iterator<Range>::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 }}} // namespace boost::geometry::range
#endif // BOOST_GEOMETRY_UTIL_RANGE_HPP #endif // BOOST_GEOMETRY_UTIL_RANGE_HPP

View File

@ -15,10 +15,60 @@
#include <vector> #include <vector>
#include <boost/geometry/util/range.hpp> #include <boost/geometry/util/range.hpp>
int test_main(int, char* []) namespace bgt {
template <bool MutableIterator>
struct beginner
{
template <typename Range>
typename boost::range_iterator<Range>::type
operator()(Range & rng)
{
return boost::begin(rng);
}
};
template <>
struct beginner<false>
{
template <typename Range>
typename boost::range_iterator<Range const>::type
operator()(Range & rng)
{
return boost::const_begin(rng);
}
};
template <bool MutableIterator>
struct ender
{
template <typename Range>
typename boost::range_iterator<Range>::type
operator()(Range & rng)
{
return boost::end(rng);
}
};
template <>
struct ender<false>
{
template <typename Range>
typename boost::range_iterator<Range const>::type
operator()(Range & rng)
{
return boost::const_end(rng);
}
};
} // namespace bgt
template <bool MutableIterator>
void test_all()
{ {
namespace bgr = bg::range; namespace bgr = bg::range;
bgt::beginner<MutableIterator> begin;
bgt::ender<MutableIterator> end;
std::vector<int> v; std::vector<int> v;
for (int i = 0 ; i < 20 ; ++i) 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(boost::size(v) == 14); // [0,13]
BOOST_CHECK(bgr::back(v) == 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(boost::size(v) == 13); // [0,12]
BOOST_CHECK(bgr::back(v) == 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(boost::size(v) == 10); // [0,9]
BOOST_CHECK(bgr::back(v) == 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(boost::size(v) == 9); // {0,1,3..9}
BOOST_CHECK(bgr::at(v, 1) == 1); BOOST_CHECK(bgr::at(v, 1) == 1);
BOOST_CHECK(bgr::at(v, 2) == 3); BOOST_CHECK(bgr::at(v, 2) == 3);
BOOST_CHECK(bgr::back(v) == 9); 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(boost::size(v) == 9); // {0,1,3..9}
BOOST_CHECK(bgr::at(v, 1) == 1); BOOST_CHECK(bgr::at(v, 1) == 1);
BOOST_CHECK(bgr::at(v, 2) == 3); BOOST_CHECK(bgr::at(v, 2) == 3);
BOOST_CHECK(bgr::back(v) == 9); 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(boost::size(v) == 6); // {0,1,6..9}
BOOST_CHECK(bgr::at(v, 1) == 1); BOOST_CHECK(bgr::at(v, 1) == 1);
BOOST_CHECK(bgr::at(v, 2) == 6); BOOST_CHECK(bgr::at(v, 2) == 6);
BOOST_CHECK(bgr::back(v) == 9); 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(boost::size(v) == 5); // {1,6..9}
BOOST_CHECK(bgr::at(v, 0) == 1); BOOST_CHECK(bgr::at(v, 0) == 1);
BOOST_CHECK(bgr::at(v, 1) == 6); BOOST_CHECK(bgr::at(v, 1) == 6);
BOOST_CHECK(bgr::back(v) == 9); 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(boost::size(v) == 2); // {8,9}
BOOST_CHECK(bgr::at(v, 0) == 8); BOOST_CHECK(bgr::at(v, 0) == 8);
BOOST_CHECK(bgr::at(v, 1) == 9); BOOST_CHECK(bgr::at(v, 1) == 9);
BOOST_CHECK(bgr::back(v) == 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); BOOST_CHECK(boost::size(v) == 0);
}
int test_main(int, char* [])
{
test_all<true>();
test_all<false>();
return 0; return 0;
} }