Skip to content
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

Implement P2443R1 views::chunk_by #2565

Merged
merged 8 commits into from
Mar 14, 2022
Merged

Conversation

cpplearner
Copy link
Contributor

This implements P2443R1 views::chunk_by.

Fixes #2540.

@cpplearner cpplearner requested a review from a team as a code owner February 13, 2022 11:07
Copy link
Contributor

@miscco miscco left a comment

Choose a reason for hiding this comment

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

I wanted to start this yesterday evening but my wife saved me with watching "The expanse", so I am double happy

stl/inc/ranges Show resolved Hide resolved
stl/inc/ranges Outdated

_Iterator() = default;

_NODISCARD constexpr value_type operator*() const {
Copy link
Contributor

Choose a reason for hiding this comment

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

I wanted to complain about lack of noexcept(is_nothrow_copy_constructible_v<iterator_t<_Vw>>) /* strengthen */

That said it seems we were a bit lazy there with subrange Should we still add it given that we pretty sure know whether it may throw or not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This function could also throw if ITERATOR_DEBUG_LEVEL is non-zero and either _Current != _Next throws or _STL_VERIFY calls a user-defined handler that throws. I wasn't sure what to do in this scenario.

That said, <ranges> already has functions that perform similar checks and are noexcept. See also #1269.

stl/inc/ranges Outdated
_STL_VERIFY(_Current != _Next, "cannot increment chunk_by_view iterator past end");
#endif // _ITERATOR_DEBUG_LEVEL != 0
_Current = _Next;
_Next = _Parent->_Find_next(_Current);
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 correct, but gave me a little pause, because I had expected _Next as the argument not the updated _Current.

Copy link
Contributor Author

@cpplearner cpplearner Feb 13, 2022

Choose a reason for hiding this comment

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

This is what P2443R1 says, but I agree with you that _Next feels better.

stl/inc/ranges Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
@cpplearner cpplearner force-pushed the chunk_by branch 2 times, most recently from e87708b to 1dee182 Compare February 13, 2022 17:13
@StephanTLavavej StephanTLavavej added cxx23 C++23 feature ranges C++20/23 ranges labels Feb 14, 2022
stl/inc/ranges Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
stl/inc/ranges Show resolved Hide resolved
stl/inc/ranges Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
Comment on lines +4904 to +4908
noexcept(chunk_by_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)))) requires requires {
chunk_by_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred));
} {
// clang-format on
return chunk_by_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred));
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand why, but I have observed that other views will switch to saying static_cast<T&&>(t) in their requires, despite our usual currently preferred convention of using forward elsewhere. Not sure if this matters here. Example:

STL/stl/inc/ranges

Lines 3806 to 3815 in afe0800

struct _Lazy_split_fn {
// clang-format off
template <viewable_range _Rng, class _Pat>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pat&& _Pattern) const noexcept(noexcept(
lazy_split_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern)))) requires requires {
lazy_split_view(static_cast<_Rng&&>(_Range), static_cast<_Pat&&>(_Pattern));
} {
// clang-format on
return lazy_split_view(_STD forward<_Rng>(_Range), _STD forward<_Pat>(_Pattern));
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And filter has mixed static_cast and _STD forward.

STL/stl/inc/ranges

Lines 1841 to 1844 in afe0800

template <viewable_range _Rng, class _Pr>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr&& _Pred) const noexcept(noexcept(
filter_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)))) requires requires {
filter_view(static_cast<_Rng&&>(_Range), _STD forward<_Pr>(_Pred));

And transform even uses _STD move.

STL/stl/inc/ranges

Lines 2300 to 2303 in afe0800

template <viewable_range _Rng, class _Fn>
_NODISCARD constexpr auto operator()(_Rng&& _Range, _Fn _Fun) const noexcept(noexcept(
transform_view(_STD forward<_Rng>(_Range), _STD move(_Fun)))) requires requires {
transform_view(static_cast<_Rng&&>(_Range), _STD move(_Fun));

@CaseyCarter do you remember why this was done in this way?

Copy link
Member

Choose a reason for hiding this comment

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

We don't replace all uses of forward and move with static_cast due to readability concerns. As a special exception to that rule, we do write static_cast instead of forward and move in concepts and constraints because compiler throughput concerns trump readability - at least until we could complete everything and get real numbers - and we want to avoid instantiating templates that may only ever be used in failing constraint checks.

Copy link
Member

Choose a reason for hiding this comment

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

Coda: I didn't complain here - despite that this would seemingly violate the general guideline - since there are no competing overloads of "operator() with arity 2" and no views_chunkable concept. I wouldn't mind if you decide to change this for consistency, but I won't demand it either.

tests/std/tests/P2443R1_views_chunk_by_death/test.cpp Outdated Show resolved Hide resolved
@CaseyCarter CaseyCarter self-assigned this Feb 16, 2022
stl/inc/xutility Outdated Show resolved Hide resolved
stl/inc/ranges Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
stl/inc/ranges Outdated Show resolved Hide resolved
tests/std/tests/P2443R1_views_chunk_by/test.cpp Outdated Show resolved Hide resolved
tests/std/tests/P2443R1_views_chunk_by_death/test.cpp Outdated Show resolved Hide resolved
tests/std/tests/P2443R1_views_chunk_by/test.cpp Outdated Show resolved Hide resolved
@StephanTLavavej
Copy link
Member

I've pushed a conflict-free merge with main (as there had been a submodule update) and a trivial test change.

@StephanTLavavej StephanTLavavej self-assigned this Mar 12, 2022
@StephanTLavavej
Copy link
Member

I'm mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed.

@StephanTLavavej StephanTLavavej merged commit add4401 into microsoft:main Mar 14, 2022
@StephanTLavavej
Copy link
Member

Thanks for implementing this chunky chocolate chip cookie! 🍪 🍫 😸

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cxx23 C++23 feature ranges C++20/23 ranges
Projects
None yet
Development

Successfully merging this pull request may close these issues.

P2443R1 views::chunk_by
4 participants
  翻译: