diff --git a/include/boost/geometry/util/range.hpp b/include/boost/geometry/util/range.hpp index 144988011..1870c7d6c 100644 --- a/include/boost/geometry/util/range.hpp +++ b/include/boost/geometry/util/range.hpp @@ -18,11 +18,13 @@ #include #include +#include #include #include #include #include #include +#include #include @@ -160,6 +162,55 @@ inline void pop_back(Range & rng) range::resize(rng, boost::size(rng) - 1); } +namespace detail { + +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + +template ::value_type &&, + typename std::iterator_traits::value_type + >::value> +struct copy_or_move_impl +{ + static inline OutIt apply(It first, It last, OutIt out) + { + return std::move(first, last, out); + } +}; + +template +struct copy_or_move_impl +{ + static inline OutIt apply(It first, It last, OutIt out) + { + return std::copy(first, last, out); + } +}; + +#else + +template +struct copy_or_move_impl +{ + static inline OutIt apply(It first, It last, OutIt out) + { + return std::copy(first, last, out); + } +}; + +#endif + +template +inline OutIt copy_or_move(It first, It last, OutIt out) +{ + return copy_or_move_impl::apply(first, last, out); +} + +} // namespace detail + /*! \brief Short utility to conveniently remove an element from a mutable range. It uses std::copy() and resize(). Version taking mutable iterators. @@ -177,7 +228,8 @@ erase(Range & rng, next = it; ++next; - std::copy(next, boost::end(rng), it); + //std::copy(next, boost::end(rng), it); + detail::copy_or_move(next, boost::end(rng), it); range::resize(rng, boost::size(rng) - 1); // NOTE: assuming that resize() doesn't invalidate the iterators @@ -225,7 +277,8 @@ erase(Range & rng, if ( count > 0 ) { - std::copy(last, boost::end(rng), first); + //std::copy(last, boost::end(rng), first); + detail::copy_or_move(last, boost::end(rng), first); range::resize(rng, boost::size(rng) - count); } diff --git a/test/util/range.cpp b/test/util/range.cpp index e86d278da..81e37129b 100644 --- a/test/util/range.cpp +++ b/test/util/range.cpp @@ -59,17 +59,44 @@ struct ender } }; +struct NonMovable +{ + NonMovable(int ii = 0) : i(ii) {} + NonMovable(NonMovable const& ii) : i(ii.i) {} + NonMovable & operator=(NonMovable const& ii) { i = ii.i; return *this; } + operator int() { return i; } + int i; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES +private: + NonMovable(NonMovable && ii); + NonMovable & operator=(NonMovable && ii); +#endif +}; + +struct CopyableAndMovable +{ + CopyableAndMovable(int ii = 0) : i(ii) {} + CopyableAndMovable(CopyableAndMovable const& ii) : i(ii.i) {} + CopyableAndMovable & operator=(CopyableAndMovable const& ii) { i = ii.i; return *this; } + operator int() { return i; } + int i; +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES + CopyableAndMovable(CopyableAndMovable && ii) : i(std::move(ii.i)) {} + CopyableAndMovable & operator=(CopyableAndMovable && ii) { i = std::move(ii.i); return *this; } +#endif +}; + } // namespace bgt -template +namespace bgr = bg::range; + +template void test_all() { - namespace bgr = bg::range; - bgt::beginner begin; bgt::ender end; - std::vector v; + std::vector v; for (int i = 0 ; i < 20 ; ++i) { bgr::push_back(v, i); @@ -92,7 +119,7 @@ void test_all() BOOST_CHECK(boost::size(v) == 14); // [0,13] BOOST_CHECK(bgr::back(v) == 13); - std::vector::iterator + typename std::vector::iterator it = bgr::erase(v, end(v) - 1); BOOST_CHECK(boost::size(v) == 13); // [0,12] BOOST_CHECK(bgr::back(v) == 12); @@ -143,10 +170,35 @@ void test_all() BOOST_CHECK(it == end(v)); } +void test_detail() +{ + int arr[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + bgr::detail::copy_or_move(arr + 1, arr + 10, arr); + std::vector v(10, 0); + bgr::detail::copy_or_move(v.begin() + 1, v.begin() + 10, v.begin()); + BOOST_CHECK(boost::size(v) == 10); + bgr::erase(v, v.begin() + 1); + BOOST_CHECK(boost::size(v) == 9); + + int * arr2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + bgr::detail::copy_or_move(arr2 + 1, arr2 + 10, arr2); + std::vector v2(10, 0); + bgr::detail::copy_or_move(v2.begin() + 1, v2.begin() + 10, v2.begin()); + BOOST_CHECK(boost::size(v2) == 10); + bgr::erase(v2, v2.begin() + 1); + BOOST_CHECK(boost::size(v2) == 9); +} + int test_main(int, char* []) { - test_all(); - test_all(); + test_all(); + test_all(); + test_all(); + test_all(); + test_all(); + test_all(); + + test_detail(); return 0; }