Skip to content

Conversation

cbjeukendrup
Copy link
Member

Resolves: #12219 (almost completely)

@cbjeukendrup cbjeukendrup marked this pull request as ready for review September 11, 2025 11:54
@cbjeukendrup
Copy link
Member Author

@juli27 Would you mind taking a look at this PR?

Copy link
Contributor

@juli27 juli27 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! One minor comment and two nit-picky comments.
This speeds up score loading a bit (Beethoven 9th score from ~37s down to ~32s)

Comment on lines 45 to 47
inline bool contains_if(const std::vector<T>& vec, Predicate pred)
{
return std::find_if(vec.cbegin(), vec.cend(), pred) != vec.cend();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: forwarding reference & forward to avoid copy. (std::function can heap allocate)

Suggested change
inline bool contains_if(const std::vector<T>& vec, Predicate pred)
{
return std::find_if(vec.cbegin(), vec.cend(), pred) != vec.cend();
inline bool contains_if(const std::vector<T>& vec, Predicate&& pred)
{
return std::find_if(vec.cbegin(), vec.cend(), std::forward<Predicate>(pred)) != vec.cend();

@@ -650,7 +653,7 @@ bool UndoMacro::empty() const

void UndoMacro::append(UndoMacro&& other)
{
appendChildren(&other);
appendChildren(std::forward<UndoMacro>(other));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty unusual and unsafe usage of rvalue references, because we state here that other is moved into appendChildren but then continue to use it further down this function. It works only because we don't actually move the entire UndoMacro in appendChildren but only the child commands vector. Let's get rid of the move iterator in appendChildren, which only copies the raw pointers anyway

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I pushed some code review fixes in a separate commit.

cbjeukendrup and others added 9 commits September 13, 2025 02:37
But with a std::vector range represented by a start and end iterator. Instead of popping from a list, we're now shrinking the vector range, until it's empty. Involves consistent usage of std::remove and std::remove_if, also with reverse iterators.

std::remove[_if] are of course in theory a little bit slower than std::list::remove[_if], because they need to `std::move` some values around. But according to the literature, that cost is easily outweighed by the benefits of std::vector, like cache-friendliness.
There were a few `remove` calls, but not significant enough to warrant `std::list`, given that the lists here should be relatively small.
Co-Authored-By: Julian Bühler <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

std::list abuse
2 participants