Skip to content

Optimize C++/WinRT's GetMany implementation#497

Merged
kennykerr merged 6 commits into
masterfrom
kennykerr-iterator
Jul 5, 2019
Merged

Optimize C++/WinRT's GetMany implementation#497
kennykerr merged 6 commits into
masterfrom
kennykerr-iterator

Conversation

@kennykerr

@kennykerr kennykerr commented Jul 5, 2019

Copy link
Copy Markdown
Contributor

The GetMany implementation for IIterable<T> was performing multiple traversals of the range when random access iterators weren't available. This update ensures that only a single traversal occurs in all cases and memcpy is used in more cases when the range offers random access.

I've also moved the scratch test into a separate project as the tests have become too extensive.

@kennykerr kennykerr changed the title Optimized C++/WinRT's GetMany implementation Optimize C++/WinRT's GetMany implementation Jul 5, 2019
@kennykerr kennykerr merged commit 7931803 into master Jul 5, 2019
@kennykerr kennykerr deleted the kennykerr-iterator branch July 5, 2019 21:35
m_owner->copy_n(m_current, actual, values.begin());
std::advance(m_current, actual);
return actual;
if constexpr (std::is_same_v<decltype(typename std::iterator_traits<iterator_type>::iterator_category()), std::random_access_iterator_tag>)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

std::is_same is the wrong way to light up behavior for random access iterators, as it will improperly reject C++20's contiguous_iterator_tag. The iterator tags have an inheritance chain, basically representing the strength of the iterator guarantees - continuous_iterator_tag inherits from random_access_iterator_tag, which inherits from bidirectional_iterator_tag, and so on.

What you really need to do here is use overload dispatch to specialize the behavior based on iterator "strength", as in the example at https://en.cppreference.com/w/cpp/iterator/iterator_tags.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Ah good idea. I'll do that.

++m_current;
}

return static_cast<uint32_t>(output - values.begin());

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Directly subtracting iterators is an operation that is only valid for random_access_iterator_tag, which this 'else' clause is explicitly not supposed to use. Do you have test coverage exercising this branch?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yes, this is heavily tested. In fact, I just added even more rigorous tests for this branch. #499

@kennykerr kennykerr Jul 8, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I think the confusion here is that the subtraction is not on the input but on the output. 😉

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh yeah, that's totally safe to do on the output. Thanks for pointing that out. 👍

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.

3 participants