mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
[range] Optimize erase() in C++11 - use std::move() instead of std::copy() if possible.
This commit is contained in:
parent
a0a296877f
commit
cd2e17b102
@ -18,11 +18,13 @@
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/concept_check.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/range/concepts.hpp>
|
||||
#include <boost/range/begin.hpp>
|
||||
#include <boost/range/end.hpp>
|
||||
#include <boost/range/empty.hpp>
|
||||
#include <boost/range/size.hpp>
|
||||
#include <boost/type_traits/is_convertible.hpp>
|
||||
|
||||
#include <boost/geometry/core/mutable_range.hpp>
|
||||
|
||||
@ -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 <typename It,
|
||||
typename OutIt = It,
|
||||
bool UseMove = boost::is_convertible
|
||||
<
|
||||
typename std::iterator_traits<It>::value_type &&,
|
||||
typename std::iterator_traits<OutIt>::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 <typename It, typename OutIt>
|
||||
struct copy_or_move_impl<It, OutIt, false>
|
||||
{
|
||||
static inline OutIt apply(It first, It last, OutIt out)
|
||||
{
|
||||
return std::copy(first, last, out);
|
||||
}
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
template <typename It, typename OutIt = It, bool /*UseMove*/ = false>
|
||||
struct copy_or_move_impl
|
||||
{
|
||||
static inline OutIt apply(It first, It last, OutIt out)
|
||||
{
|
||||
return std::copy(first, last, out);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
template <typename It, typename OutIt>
|
||||
inline OutIt copy_or_move(It first, It last, OutIt out)
|
||||
{
|
||||
return copy_or_move_impl<It, OutIt>::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);
|
||||
}
|
||||
|
||||
|
@ -59,17 +59,44 @@ struct ender<false>
|
||||
}
|
||||
};
|
||||
|
||||
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 <bool MutableIterator>
|
||||
namespace bgr = bg::range;
|
||||
|
||||
template <typename T, bool MutableIterator>
|
||||
void test_all()
|
||||
{
|
||||
namespace bgr = bg::range;
|
||||
|
||||
bgt::beginner<MutableIterator> begin;
|
||||
bgt::ender<MutableIterator> end;
|
||||
|
||||
std::vector<int> v;
|
||||
std::vector<T> 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<int>::iterator
|
||||
typename std::vector<T>::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<int> 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<int*> 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<true>();
|
||||
test_all<false>();
|
||||
test_all<int, true>();
|
||||
test_all<int, false>();
|
||||
test_all<bgt::NonMovable, true>();
|
||||
test_all<bgt::NonMovable, false>();
|
||||
test_all<bgt::CopyableAndMovable, true>();
|
||||
test_all<bgt::CopyableAndMovable, false>();
|
||||
|
||||
test_detail();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user