mirror of
https://github.com/boostorg/geometry.git
synced 2025-05-09 23:24:02 +00:00
[range] Add support for invalidating resize() and workarounds for MSVC and MinGW.
Using of the iterator returned by erase() caused assertion failures (false positive) on MSVC with iterator debugging enabled. MSVC std::vector can't store non-movable objects if rvalue references are supported. MinGW std::vector can't store pointers.
This commit is contained in:
parent
81ea76fdb9
commit
ba0906369e
@ -221,6 +221,9 @@ erase(Range & rng,
|
||||
BOOST_ASSERT(!boost::empty(rng));
|
||||
BOOST_ASSERT(it != boost::end(rng));
|
||||
|
||||
typename boost::range_difference<Range>::type const
|
||||
d = std::distance(boost::begin(rng), it);
|
||||
|
||||
typename boost::range_iterator<Range>::type
|
||||
next = it;
|
||||
++next;
|
||||
@ -228,8 +231,13 @@ erase(Range & rng,
|
||||
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
|
||||
return it;
|
||||
// NOTE: In general this should be sufficient:
|
||||
// return it;
|
||||
// But in MSVC using the returned iterator causes
|
||||
// assertion failures when iterator debugging is enabled
|
||||
// Furthermore the code below should work in the case if resize()
|
||||
// invalidates iterators when the container is resized down.
|
||||
return boost::begin(rng) + d;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -262,10 +270,11 @@ erase(Range & rng,
|
||||
typename boost::range_iterator<Range>::type first,
|
||||
typename boost::range_iterator<Range>::type last)
|
||||
{
|
||||
typename std::iterator_traits
|
||||
<
|
||||
typename boost::range_iterator<Range>::type
|
||||
>::difference_type const diff = std::distance(first, last);
|
||||
typename boost::range_difference<Range>::type const
|
||||
d = std::distance(boost::begin(rng), first);
|
||||
|
||||
typename boost::range_difference<Range>::type const
|
||||
diff = std::distance(first, last);
|
||||
BOOST_ASSERT(diff >= 0);
|
||||
|
||||
std::size_t const count = static_cast<std::size_t>(diff);
|
||||
@ -275,9 +284,16 @@ erase(Range & rng,
|
||||
{
|
||||
detail::copy_or_move(last, boost::end(rng), first);
|
||||
range::resize(rng, boost::size(rng) - count);
|
||||
|
||||
// NOTE: In general this should be sufficient:
|
||||
// return first;
|
||||
// But in MSVC using the returned iterator causes
|
||||
// assertion failures when iterator debugging is enabled
|
||||
// Furthermore the code below should work in the case if resize()
|
||||
// invalidates iterators when the container is resized down.
|
||||
return boost::begin(rng) + d;
|
||||
}
|
||||
|
||||
// NOTE: assuming that resize() doesn't invalidate the iterators
|
||||
return first;
|
||||
}
|
||||
|
||||
|
@ -172,29 +172,41 @@ void test_all()
|
||||
|
||||
void test_detail()
|
||||
{
|
||||
int arr[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
bgr::detail::copy_or_move(arr + 1, arr + 10, arr);
|
||||
BOOST_CHECK(arr[0] == 1);
|
||||
|
||||
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};
|
||||
bgt::NonMovable * arr2[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
bgt::NonMovable foo;
|
||||
arr2[1] = &foo;
|
||||
bgr::detail::copy_or_move(arr2 + 1, arr2 + 10, arr2);
|
||||
std::vector<int*> v2(10, 0);
|
||||
BOOST_CHECK(arr2[0] == &foo);
|
||||
|
||||
// Storing pointers in a std::vector is not possible in MinGW C++98
|
||||
#if __cplusplus >= 201103L
|
||||
std::vector<bgt::NonMovable*> 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);
|
||||
#endif
|
||||
}
|
||||
|
||||
int test_main(int, char* [])
|
||||
{
|
||||
test_all<int, true>();
|
||||
test_all<int, false>();
|
||||
// Storing non-movable elements in a std::vector is not possible in MSVC
|
||||
#ifndef _MSC_VER
|
||||
test_all<bgt::NonMovable, true>();
|
||||
test_all<bgt::NonMovable, false>();
|
||||
#endif
|
||||
test_all<bgt::CopyableAndMovable, true>();
|
||||
test_all<bgt::CopyableAndMovable, false>();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user