Skip to content

Commit

Permalink
Implement constexpr algorithms.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
BillyONeal committed Jan 21, 2020
1 parent 2989323 commit ad2c84f
Show file tree
Hide file tree
Showing 9 changed files with 630 additions and 499 deletions.
2 changes: 1 addition & 1 deletion llvm-project
Submodule llvm-project updated 1537 files
401 changes: 235 additions & 166 deletions stl/inc/algorithm

Large diffs are not rendered by default.

57 changes: 29 additions & 28 deletions stl/inc/numeric
Original file line number Diff line number Diff line change
Expand Up @@ -75,25 +75,26 @@ _NODISCARD _CONSTEXPR20_ICE _Ty reduce(const _InIt _First, const _InIt _Last, _T
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
if constexpr (_Plus_on_arithmetic_ranges_reduction_v<_Unwrapped_t<const _InIt&>, _Ty, _BinOp>) {
#ifdef __cpp_lib_is_constant_evaluated
// TRANSITION, DevCom-878972
if (_STD is_constant_evaluated()) {
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713
}
return _Val;
} else
#endif // __cpp_lib_is_constant_evaluated
{
if constexpr (_Plus_on_arithmetic_ranges_reduction_v<_Unwrapped_t<const _InIt&>, _Ty, _BinOp>) {
(void) _Reduce_op; // TRANSITION, VSO-486357
return _Reduce_plus_arithmetic_ranges(_UFirst, _ULast, _Val);
} else {
if (_STD is_constant_evaluated()) {
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713
}

return _Val;
} else
#endif
{
(void) _Reduce_op; // TRANSITION, VSO-486357
return _Reduce_plus_arithmetic_ranges(_UFirst, _ULast, _Val);
}
} else {
for (; _UFirst != _ULast; ++_UFirst) {
_Val = _Reduce_op(_STD move(_Val), *_UFirst); // Requirement missing from N4713
}

return _Val;
}
}

Expand Down Expand Up @@ -211,28 +212,28 @@ _NODISCARD _CONSTEXPR20_ICE _Ty transform_reduce(
auto _UFirst1 = _Get_unwrapped(_First1);
const auto _ULast1 = _Get_unwrapped(_Last1);
auto _UFirst2 = _Get_unwrapped_n(_First2, _Idl_distance<_InIt1>(_UFirst1, _ULast1));
if constexpr (_Default_ops_transform_reduce_v<_Unwrapped_t<const _InIt1&>, _Unwrapped_t<const _InIt2&>, _Ty,
_BinOp1, _BinOp2>) {
#ifdef __cpp_lib_is_constant_evaluated
// TRANSITION, DevCom-878972
if (_STD is_constant_evaluated()) {
for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4713
}
return _Val;
} else
#endif // __cpp_lib_is_constant_evaluated
{
if constexpr (_Default_ops_transform_reduce_v<_Unwrapped_t<const _InIt1&>, _Unwrapped_t<const _InIt2&>, _Ty,
_BinOp1, _BinOp2>) {
(void) _Reduce_op; // TRANSITION, VSO-486357
(void) _Transform_op; // TRANSITION, VSO-486357
return _Transform_reduce_arithmetic_defaults(_UFirst1, _ULast1, _UFirst2, _STD move(_Val));
} else {
// TRANSITION, DevCom-878972
if (_STD is_constant_evaluated()) {
for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
_Val =
_Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4713
}
return _Val;
} else
#endif // __cpp_lib_is_constant_evaluated
{
(void) _Reduce_op; // TRANSITION, VSO-486357
(void) _Transform_op; // TRANSITION, VSO-486357
return _Transform_reduce_arithmetic_defaults(_UFirst1, _ULast1, _UFirst2, _STD move(_Val));
}
} else {
for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2) {
_Val = _Reduce_op(_STD move(_Val), _Transform_op(*_UFirst1, *_UFirst2)); // Requirement missing from N4713
}
return _Val;
}
}

Expand Down
4 changes: 2 additions & 2 deletions stl/inc/type_traits
Original file line number Diff line number Diff line change
Expand Up @@ -1949,10 +1949,10 @@ template <class _Ty, enable_if_t<is_move_constructible_v<_Ty> && is_move_assigna
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv
template <class _Ty, int _Enabled = 0>
#endif // _HAS_CXX17
void swap(_Ty&, _Ty&) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>);
_CONSTEXPR20 void swap(_Ty&, _Ty&) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>);

template <class _Ty, size_t _Size, enable_if_t<_Is_swappable<_Ty>::value, int> = 0>
void swap(_Ty (&)[_Size], _Ty (&)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value);
_CONSTEXPR20 void swap(_Ty (&)[_Size], _Ty (&)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value);

// STRUCT TEMPLATE _Swappable_with_helper
template <class _Ty1, class _Ty2, class = void>
Expand Down
11 changes: 6 additions & 5 deletions stl/inc/utility
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty& _Max_value

// FUNCTION TEMPLATE iter_swap (from <algorithm>)
template <class _FwdIt1, class _FwdIt2>
void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right
_CONSTEXPR20 void iter_swap(_FwdIt1 _Left, _FwdIt2 _Right) { // swap *_Left and *_Right
swap(*_Left, *_Right);
}

// FUNCTION TEMPLATE swap
template <class _Ty, size_t _Size, enable_if_t<_Is_swappable<_Ty>::value, int> _Enabled>
void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value) {
_CONSTEXPR20 void swap(_Ty (&_Left)[_Size], _Ty (&_Right)[_Size]) noexcept(_Is_nothrow_swappable<_Ty>::value) {
if (&_Left != &_Right) {
_Ty* _First1 = _Left;
_Ty* _Last1 = _First1 + _Size;
Expand All @@ -61,15 +61,16 @@ template <class _Ty, enable_if_t<is_move_constructible_v<_Ty> && is_move_assigna
#else // ^^^ _HAS_CXX17 / !_HAS_CXX17 vvv
template <class _Ty, int _Enabled>
#endif // _HAS_CXX17
void swap(_Ty& _Left, _Ty& _Right) noexcept(is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) {
_CONSTEXPR20 void swap(_Ty& _Left, _Ty& _Right) noexcept(
is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) {
_Ty _Tmp = _STD move(_Left);
_Left = _STD move(_Right);
_Right = _STD move(_Tmp);
}

// FUNCTION TEMPLATE _Swap_adl
template <class _Ty>
void _Swap_adl(_Ty& _Left, _Ty& _Right) noexcept(_Is_nothrow_swappable<_Ty>::value) {
_CONSTEXPR20 void _Swap_adl(_Ty& _Left, _Ty& _Right) noexcept(_Is_nothrow_swappable<_Ty>::value) {
swap(_Left, _Right);
}

Expand Down Expand Up @@ -566,7 +567,7 @@ _NODISCARD constexpr const _Ty2&& get(

// FUNCTION TEMPLATE exchange
template <class _Ty, class _Other = _Ty>
_Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept(
_CONSTEXPR20 _Ty exchange(_Ty& _Val, _Other&& _New_val) noexcept(
conjunction_v<is_nothrow_move_constructible<_Ty>, is_nothrow_assignable<_Ty&, _Other>>) /* strengthened */ {
// assign _New_val to _Val, return previous _Val
_Ty _Old_val = static_cast<_Ty&&>(_Val);
Expand Down
6 changes: 4 additions & 2 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -1997,7 +1997,8 @@ struct _Alloc_temporary {

// FUNCTION TEMPLATE remove
template <class _FwdIt, class _Ty>
_NODISCARD _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { // remove each matching _Val
_NODISCARD _CONSTEXPR20 _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) {
// remove each matching _Val
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
Expand All @@ -2018,7 +2019,8 @@ _NODISCARD _FwdIt remove(_FwdIt _First, const _FwdIt _Last, const _Ty& _Val) { /

// FUNCTION TEMPLATE remove_if
template <class _FwdIt, class _Pr>
_NODISCARD _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) { // remove each satisfying _Pred
_NODISCARD _CONSTEXPR20 _FwdIt remove_if(_FwdIt _First, const _FwdIt _Last, _Pr _Pred) {
// remove each satisfying _Pred
_Adl_verify_range(_First, _Last);
auto _UFirst = _Get_unwrapped(_First);
const auto _ULast = _Get_unwrapped(_Last);
Expand Down
Loading

0 comments on commit ad2c84f

Please sign in to comment.