-
Notifications
You must be signed in to change notification settings - Fork 852
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Left shift in StaticVector::erase(), add tests #7879
Conversation
Currently the behaviour of StaticVector::erase() is broken. Whereas it should work just like std::vector's erase(), it just destroys items and leaves them in place. This commit changes the behaviour so that it first calls std::move and moves all items back, then proceeds to call std::destroy_at() on the elements at the back of the array.
Fix clang-format error
15aecaf
to
1a7fff1
Compare
Style fixups
clang-format complaints again
Consider using the term "Shift" instead of "Shuffle" as shuffle indicates, at least to me, an element of random reordering. |
This implements the following tests: - StaticVector_push_full() is a static test that fills the array and checks its expected size and elements. - StaticVector_erase() is a static test that tests for several edge cases. These edge cases are: - Erasing from the beginning of an array. - Erasing from the end of an array - Erasing out of bounds ahead of the array's head. - Erasing out of bounds behind the array's tail. - StaticVector_erase_range() is a mixed static and random test that tests that ranges are appropriately erased, including ranges of 0. Static test erasures of zero size Style fixups
for -> while
1ab250b
to
066f883
Compare
Sorry for the messy commit history. I always forget to run There is at this point a possible change that I'd like to discuss here. Currently
Would it be better to return early as it does presently, or should it fix up these values to within bounds? Or should it perhaps do an assertion for these cases? |
I think we both made the mistake thinking this would be a quick little change :D |
Adding asserts will be fine, I don't know exactly where in the spec it's defined but usually the expectation is the caller will do the right thing and not try erase invalid values. For example, you can
would then trigger an assert failure (or crash in release builds). and for
would fail the assert
|
I've added the asserts and also added test cases for them, which are disabled in release builds. In debug builds the tests will also test assertions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, one more nit and pointing out something you did that I didn't think of but makes sense for the other test case too :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice work, sorry for the back and forth for what is a fairly isolated change 😅
looks correct to me but it’s getting late in the evening so I’ll hope a second set of eyes can do the merge (or I’ll check again tomorrow)
I appreciate the review, don't worry about the back and forth. Thank you. |
This commit correctly implements StaticVector::erase() and cleans up the code that was here before. Specifically, this code attempts to closely mirror libstdc++'s implementation of std::vector::erase(): - move elements left and overwrite erased elements - clean up tail elements with std::destroy() - shrink the size of the vector
So I've researched this more, discussed this some more on Discord, and looked at a libstdc++ implementation of _M_erase(iterator __position)
{
if (__position + 1 != end())
_GLIBCXX_MOVE3(__position + 1, end(), __position);
--this->_M_impl._M_finish;
_Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish);
_GLIBCXX_ASAN_ANNOTATE_SHRINK(1);
return __position;
} This code moves In the new commit, the elements being moved to are overwritten, both with move assignable and copy assignable types. The elements trailing at the end are now garbage, and need to be cleaned up, where int *ptr1 = malloc(sizeof(*ptr1));
int *ptr2 = malloc(sizeof(*ptr2));
free(ptr1);
ptr1 = ptr2;
ptr2 = NULL; The build is failing right now, but only because of a CMake update in the build environment. |
Hello,
While I was working on using
StaticVector
for vendor item arrays, I noticed thatStaticVector::erase()
doesn't seem to behave as expected. I asked about this on Discord and @glebm concluded it is a bug, and says that it is intended to work exactly likestd::vector
's erase.The following changes have been made to
static_vector.hpp
:std::move
is called beforestd::destroy_at
, shifting items left.std::destroy_at()
now destroys the entries at the back of the array after the move.StaticVector::clear()
returns early if there are no member items.I am not an expert in C++ and am not 100% confident in this PR or the changes made, so feedback is greatly appreciated.
Regards,
Yggdrasill