-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Implement constexpr algorithms. #425
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 constexpr algorithms. #425
Conversation
|
FYI I haven't submitted an internal PR yet because I'm still working on adding tests, but wanted GH contributors to be able to see this when it was done. |
stl/inc/xutility
Outdated
|
|
||
| // ALGORITHM DISPATCH TRAITS | ||
| template <class> | ||
| class move_iterator; |
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.
Can this declaration move (pun intended) as well?
stl/inc/xutility
Outdated
|
|
||
| // FUNCTION TEMPLATE copy | ||
| template <class _Source, class _Dest> | ||
| struct _Ptr_cat_helper { // determines _Ptr_cat's result in the most general case |
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.
All of these comments on _Ptr_cat_helper and its specializations should feed the flames, IMO.
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.
Hmm I think on the partial specializations they serve to motivate why the partial specialization is OK. I removed some of the obvious ones.
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.
To me, "determines _Ptr_cat's result" says that _Ptr_cat_helper implements _Ptr_cat - which is ~obvious - and each of the "when [condition]" bits simply repeat the pattern that the partial specialization matches:
-
_Ptr_cat_helper<_Elem, _Elem>..."when the types are the same" -
_Ptr_cat_helper<_Anything*, const _Anything*>..."when all we do is addconstto a pointer"
I don't think the comments provide any new information or justification.
EDIT: Not that it's worth wasting our time arguing about, either. Feel free to apply or ignore this comment and mark "Resolved"; I've said my piece ;)
stl/inc/xutility
Outdated
| struct _Ptr_copy_cat<_Source*, _Dest*> | ||
| : conditional_t<is_trivially_assignable_v<_Dest&, _Source&>, | ||
| _Ptr_cat_helper<remove_cv_t<_Source>, remove_cv_t<_Dest>>, _False_copy_cat> { | ||
| }; // return pointer copy optimization category for pointers |
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.
I thought we put the comment inside the {} when {}; // comment won't all fit on one line?
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.
The red text contradicts my recollection. 🤷♂ Feel free to humor me or ignore this comment; I'm not sure I care either way.
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.
If they go away completely it doesn't matter where they are :)
stl/inc/xutility
Outdated
| _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { | ||
| _CONSTEXPR20_ICE _OutIt _Copy_unchecked(_InIt _First, _InIt _Last, _OutIt _Dest) { | ||
| // copy [_First, _Last) to [_Dest, ...) | ||
| // note: _Copy_unchecked is called directly from elsewhere in the STL |
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.
| // note: _Copy_unchecked is called directly from elsewhere in the STL | |
| // note: _Copy_unchecked has callers other than copy |
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.
Ditto 3915 and 4006.
stl/inc/algorithm
Outdated
| _NODISCARD pair<_InIt1, _RightTy*> mismatch(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], | ||
| _NODISCARD _CONSTEXPR20 pair<_InIt1, _RightTy*> mismatch(const _InIt1 _First1, const _InIt1 _Last1, | ||
| _RightTy (&_First2)[_RightSize], | ||
| _Pr _Pred) { // return [_First1, _Last1)/[_First2, ...) mismatch using _Pred |
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.
Wrap comment?
stl/inc/algorithm
Outdated
| _OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], const _OutIt _Dest, | ||
| _CONSTEXPR20 _OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, _RightTy (&_First2)[_RightSize], | ||
| const _OutIt _Dest, | ||
| _Fn _Func) { // transform [_First1, _Last1) and [_First2, ...), array source |
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.
Wrap comment.
stl/inc/algorithm
Outdated
| template <class _OutIt, class _Diff, class _Fn> | ||
| _OutIt generate_n(_OutIt _Dest, const _Diff _Count_raw, _Fn _Func) { // replace [_Dest, _Dest + _Count) with _Func() | ||
| _CONSTEXPR20 _OutIt generate_n( | ||
| _OutIt _Dest, const _Diff _Count_raw, _Fn _Func) { // replace [_Dest, _Dest + _Count) with _Func() |
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.
Wrap comment.
stl/inc/algorithm
Outdated
| template <class _InIt, class _OutIt, class _Ty> | ||
| _OutIt remove_copy(_InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Val) { // copy omitting each matching _Val | ||
| _CONSTEXPR20 _OutIt remove_copy( | ||
| _InIt _First, _InIt _Last, _OutIt _Dest, const _Ty& _Val) { // copy omitting each matching _Val |
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.
Wrap.
|
FYI to reviewers, I'm going to wait till #423 merges to resolve comments here. |
Resolves microsoftGH-6 ( P0202R3 ), microsoftGH-38 ( P0879R0 ), and drive-by fixes microsoftGH-414. Everywhere: Add constexpr, _CONSTEXPR20, and _CONSTEXPR20_ICE to things. skipped_tests.txt: Turn on all tests previously blocked by missing constexpr algorithms (and exchange and swap). Mark those algorithms that cannot be turned on that we have outstanding PRs for with their associated PRs. yvals_core.h: Turn on feature test macros. xutility: * Move the _Ptr_cat family down to copy, and fix associated SHOUTY comments to indicate that this is really an implementation detail of copy, not something the rest of the standard library intends to use directly. Removed and clarified some of the comments as requested by Casey Carter. * Extract _Copy_n_core which implements copy_n using only the core language (rather than memcpy-as-an-intrinsic). Note that we cannot use __builtin_memcpy or similar to avoid the is_constant_evaluated check here; builtin_memcpy only works in constexpr contexts when the inputs are of type char. numeric: Refactor as suggested by microsoftGH-414.
c09c7d3 to
ad2c84f
Compare
| #define __cpp_lib_to_array 201907L | ||
| #define __cpp_lib_type_identity 201806L | ||
| #define __cpp_lib_unwrap_ref 201811L | ||
|
|
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.
The newly-implemented features need to be listed in the comment at the top.
stl/inc/numeric
Outdated
| } else { | ||
| if (_STD is_constant_evaluated()) { | ||
| for (; _UFirst != _ULast; ++_UFirst) { | ||
| _Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713 |
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.
This repeats the "classic implementation"; for #414 I hoped that we would be able to avoid that. Did you intend to choose another approach?
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.
Nothing suggested in #414 avoids repeating the classic implementation, only moving it such only one copy of it is considered for a given setting of the if constexpr branch.
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.
I suggested avoiding the repetition. See:
So perhaps the best pattern is:
if constexpr (_Plus_on_arithmetic_ranges_reduction_v) {
if (!_STD is_constant_evaluated()) {
return _Reduce_plus_arithmetic_ranges(ARGS);
}
}
return CLASSIC_IMPLEMENTATION;
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.
I guess when you filed that you made it unrelated to the original submission.
I believe that pattern will trip DevCom-889321.
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.
The proposed pattern is is_constant_evaluated within if constexpr; your filed bug is about if constexpr within is_constant_evaluated.
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.
OTOH DevCom-889321 was the opposite (if constexpr inside is_constant_evaluated). Let me try this and see if it works out...
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.
Hmmm well it seems to work so I'm not going to look a gift horse in the mouth ¯\_(ツ)_/¯
stl/inc/algorithm
Outdated
| // FUNCTION TEMPLATE swap_ranges | ||
| template <class _FwdIt1, class _FwdIt2> | ||
| _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { | ||
| constexpr _FwdIt2 _Swap_ranges_unchecked(_FwdIt1 _First1, const _FwdIt1 _Last1, _FwdIt2 _First2) { |
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.
Why is this plain constexpr? This calls iter_swap which is _CONSTEXPR20.
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.
I guess nobody cares about that IFNDR
stl/inc/algorithm
Outdated
|
|
||
| // FUNCTION TEMPLATE merge | ||
| inline _Distance_unknown _Idl_dist_add(_Distance_unknown, _Distance_unknown) { | ||
| constexpr _Distance_unknown _Idl_dist_add(_Distance_unknown, _Distance_unknown) { |
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.
Pre-existing: The _Idl_dist_add overloads should be _NODISCARD.
stl/inc/xutility
Outdated
|
|
||
| template <class _FwdIt1, class _FwdIt2> | ||
| bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { | ||
| _CONSTEXPR20 bool is_permutation(_FwdIt1 _First1, _FwdIt1 _Last1, _FwdIt2 _First2) { |
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.
Pre-existing: This Standard overload is egregiously and mysteriously missing _NODISCARD.
* _Swap_ranges_unchecked => _CONSTEXPR20 * _Idl_dist_add => _NODISCARD (and remove DinkumComments) * is_permutation => _NODISCARD * Add yvals_core.h comments.
| } | ||
| return _Val; | ||
| } else | ||
| // TRANSITION, DevCom-878972 |
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.
Is this still TRANSITION now that you've eliminated the code duplication?
stl/inc/xutility
Outdated
|
|
||
| // FUNCTION TEMPLATE copy_n | ||
| template <class _InIt, class _Diff, class _OutIt> | ||
| constexpr _OutIt _Copy_n_core(_InIt _First, _Diff _Count, _OutIt _Dest) {} |
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.
_Copy_n_core appears to be unused, and it has an empty function body.
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.
🙄
StephanTLavavej
left a comment
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, thanks for working on this!
|
Microsoft-internal MSVC-PR-224184 completed, so I went ahead and merged this. |
In GH-425 I was forced to add a dead initialization for the _Count variable in _Sort_unchecked in order to comply with constexpr rules. Also, _Sort_unchecked had somewhat complex assignment-in-conditional-expressions going on. This change moves the code around such that the _Count variable is assigned once. Also: * Consistently test _ISORT_MAX with <= where possible, and make that an _INLINE_VAR constexpr variable. * Remove _Count guards of 1 in front of _Insertion_sort_unchecked for consistency. I did performance testing and there was no measurable difference in keeping this check, and it's more code to reason about. * Avoid needless casts of _ISORT_MAX given that it is now a constexpr constant.
Resolves GH-6 ( P0202R3 ), GH-38 ( P0879R0 ), and drive-by fixes GH-414.
Constexprizes the following algorithms by adding constexpr, _CONSTEXPR20, and _CONSTEXPR20_ICE to things:
Specific notes:
skipped_tests.txt: Turn on all tests previously blocked by missing constexpr algorithms (andexchangeandswap). Mark those algorithms that cannot be turned on that we have outstanding PRs for with their associated PRs.yvals_core.h: Turn on feature test macros.xutility: Move the _Ptr_cat family down to copy, and fix associated SHOUTY comments to indicate that this is really an implementation detail of copy, not something the rest of the standard library intends to use directly. Removed and clarified some of the comments as requested by Casey Carter.Updates the llvm submodule to get llvm/llvm-project@6d8abe4
Checklist
Be sure you've read README.md and understand the scope of this repo.
If you're unsure about a box, leave it unchecked. A maintainer will help you.
_Uglyas perhttps://eel.is/c++draft/lex.name#3.1 or there are no product code changes.
verified by an STL maintainer before automated testing is enabled on GitHub,
leave this unchecked for initial submission).
members, adding virtual functions, changing whether a type is an aggregate
or trivially copyable, etc.).
the C++ Working Draft (including any cited standards), other WG21 papers
(excluding reference implementations outside of proposed standard wording),
and LWG issues as reference material. If they were derived from a project
that's already listed in NOTICE.txt, that's fine, but please mention it.
If they were derived from any other project (including Boost and libc++,
which are not yet listed in NOTICE.txt), you must mention it here,
so we can determine whether the license is compatible and what else needs
to be done.