diff --git a/stl/inc/algorithm b/stl/inc/algorithm index 945936ee546..81e5b8548a0 100644 --- a/stl/inc/algorithm +++ b/stl/inc/algorithm @@ -1554,8 +1554,9 @@ namespace ranges { template requires indirectly_copyable, _Out> constexpr copy_result, _Out> operator()(_Rng&& _Range, _Out _Result) const { - auto _First = _RANGES begin(_Range); - auto _UResult = _RANGES _Copy_unchecked(_Get_unwrapped(_STD move(_First)), _Uend(_Range), _STD move(_Result)); + auto _First = _RANGES begin(_Range); + auto _UResult = + _RANGES _Copy_unchecked(_Get_unwrapped(_STD move(_First)), _Uend(_Range), _STD move(_Result)); _Seek_wrapped(_First, _STD move(_UResult.in)); return {_STD move(_First), _STD move(_UResult.out)}; } @@ -1589,6 +1590,39 @@ namespace ranges { }; inline constexpr _Copy_n_fn copy_n{_Not_quite_object::_Construct_tag{}}; + + // ALIAS TEMPLATE copy_backward_result + template + using copy_backward_result = in_out_result<_In, _Out>; + + // VARIABLE ranges::copy_backward + class _Copy_backward_fn : private _Not_quite_object { + public: + using _Not_quite_object::_Not_quite_object; + + // clang-format off + template _Se1, bidirectional_iterator _It2> + requires indirectly_copyable<_It1, _It2> + constexpr copy_backward_result<_It1, _It2> operator()(_It1 _First, _Se1 _Last, _It2 _Result) const { + _Adl_verify_range(_First, _Last); + auto _UFirst = _Get_unwrapped(_STD move(_First)); + auto _ULast = _Get_final_iterator_unwrapped<_It1>(_UFirst, _STD move(_Last)); + _Seek_wrapped(_First, _ULast); + _Result = _Copy_backward_unchecked(_STD move(_UFirst), _STD move(_ULast), _STD move(_Result)); + return {_STD move(_First), _STD move(_Result)}; + } + + template + requires indirectly_copyable, _It> + constexpr copy_backward_result, _It> operator()(_Rng&& _Range, _It _Result) const { + auto _ULast = _Get_final_iterator_unwrapped(_Range); + _Result = _Copy_backward_unchecked(_Ubegin(_Range), _ULast, _STD move(_Result)); + return {_Rewrap_iterator(_Range, _STD move(_ULast)), _STD move(_Result)}; + } + // clang-format on + }; + + inline constexpr _Copy_backward_fn copy_backward{_Not_quite_object::_Construct_tag{}}; } // namespace ranges #endif // __cpp_lib_concepts @@ -2573,7 +2607,8 @@ namespace ranges { if constexpr (sized_sentinel_for<_Se, _It>) { const auto _Dist = _ULast - _UFirst; - auto _UResult = _Search_n_sized(_STD move(_UFirst), _Dist, _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); + auto _UResult = + _Search_n_sized(_STD move(_UFirst), _Dist, _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_subrange>(_First, _STD move(_UResult)); } else { auto _UResult = _Search_n_unsized( @@ -2584,8 +2619,8 @@ namespace ranges { template requires indirectly_comparable, const _Ty*, _Pr, _Pj> - _NODISCARD constexpr borrowed_subrange_t<_Rng> operator()( - _Rng&& _Range, const range_difference_t<_Rng> _Count, const _Ty& _Val, _Pr _Pred = {}, _Pj _Proj = {}) const { + _NODISCARD constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, const range_difference_t<_Rng> _Count, + const _Ty& _Val, _Pr _Pred = {}, _Pj _Proj = {}) const { auto _First = _RANGES begin(_Range); if (_Count <= 0) { @@ -2599,8 +2634,8 @@ namespace ranges { _Search_n_sized(_Get_unwrapped(_First), _Dist, _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_subrange>(_First, _STD move(_UResult)); } else { - auto _UResult = _Search_n_unsized(_Get_unwrapped(_First), _Uend(_Range), _Val, - _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); + auto _UResult = _Search_n_unsized( + _Get_unwrapped(_First), _Uend(_Range), _Val, _Count, _Pass_fn(_Pred), _Pass_fn(_Proj)); return _Rewrap_subrange>(_First, _STD move(_UResult)); } } @@ -4562,7 +4597,8 @@ namespace ranges { } // clang-format off - template , _Pj>> _Pr> + template , _Pj>> _Pr> requires permutable> constexpr borrowed_subrange_t<_Rng> operator()(_Rng&& _Range, _Pr _Pred, _Pj _Proj = {}) const { auto _UResult = _Partition_unchecked(_Ubegin(_Range), _Uend(_Range), _Pass_fn(_Pred), _Pass_fn(_Proj)); diff --git a/stl/inc/xutility b/stl/inc/xutility index 26299d2612e..0728eaacc6c 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -4471,27 +4471,32 @@ _BidIt2 _Copy_backward_memmove(move_iterator<_BidIt1> _First, move_iterator<_Bid #if _HAS_IF_CONSTEXPR template -_CONSTEXPR20 _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { +_NODISCARD _CONSTEXPR20 _BidIt2 _Copy_backward_unchecked(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { // copy [_First, _Last) backwards to [..., _Dest) - _Adl_verify_range(_First, _Last); - const auto _UFirst = _Get_unwrapped(_First); - auto _ULast = _Get_unwrapped(_Last); - auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast)); - if constexpr (_Ptr_copy_cat::_Trivially_copyable) { + if constexpr (_Ptr_copy_cat<_BidIt1, _BidIt2>::_Trivially_copyable) { #ifdef __cpp_lib_is_constant_evaluated if (!_STD is_constant_evaluated()) #endif // __cpp_lib_is_constant_evaluated { - _UDest = _Copy_backward_memmove(_UFirst, _ULast, _UDest); - _Seek_wrapped(_Dest, _UDest); - return _Dest; + return _Copy_backward_memmove(_First, _Last, _Dest); } } - while (_UFirst != _ULast) { - *--_UDest = *--_ULast; + while (_First != _Last) { + *--_Dest = *--_Last; } - _Seek_wrapped(_Dest, _UDest); + + return _Dest; +} + +template +_CONSTEXPR20 _BidIt2 copy_backward(_BidIt1 _First, _BidIt1 _Last, _BidIt2 _Dest) { + // copy [_First, _Last) backwards to [..., _Dest) + _Adl_verify_range(_First, _Last); + const auto _UFirst = _Get_unwrapped(_First); + const auto _ULast = _Get_unwrapped(_Last); + const auto _UDest = _Get_unwrapped_n(_Dest, -_Idl_distance<_BidIt1>(_UFirst, _ULast)); + _Seek_wrapped(_Dest, _Copy_backward_unchecked(_UFirst, _ULast, _UDest)); return _Dest; } #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 860b9360d40..61292ad030b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -346,7 +346,7 @@ #define _MSVC_KNOWN_SEMANTICS #endif -// Controls whether the STL uses "if constexpr" internally +// Controls whether the STL uses "if constexpr" internally in C++14 mode #ifndef _HAS_IF_CONSTEXPR #ifdef __CUDACC__ #define _HAS_IF_CONSTEXPR 0 diff --git a/tests/std/include/range_algorithm_support.hpp b/tests/std/include/range_algorithm_support.hpp index d5fa87ddd08..1ec68f3fc79 100644 --- a/tests/std/include/range_algorithm_support.hpp +++ b/tests/std/include/range_algorithm_support.hpp @@ -125,6 +125,26 @@ namespace test { ptr_ = s.peek(); } // clang-format on + + [[nodiscard]] friend constexpr boolish operator==(sentinel const s, Element* const ptr) noexcept { + return {s.ptr_ == ptr}; + } + [[nodiscard]] friend constexpr boolish operator==(Element* const ptr, sentinel const s) noexcept { + return {s.ptr_ == ptr}; + } + [[nodiscard]] friend constexpr boolish operator!=(sentinel const s, Element* const ptr) noexcept { + return !(s == ptr); + } + [[nodiscard]] friend constexpr boolish operator!=(Element* const ptr, sentinel const s) noexcept { + return !(s == ptr); + } + + [[nodiscard]] friend constexpr ptrdiff_t operator-(sentinel const s, Element* const ptr) noexcept { + return s.ptr_ - ptr; + } + [[nodiscard]] friend constexpr ptrdiff_t operator-(Element* const ptr, sentinel const s) noexcept { + return ptr - s.ptr_; + } }; // clang-format off @@ -188,70 +208,86 @@ namespace test { // clang-format on template - constexpr boolish operator==(proxy_reference that) const requires CanEq { + [[nodiscard]] constexpr boolish operator==(proxy_reference that) const + requires CanEq { return {ref_ == that.peek()}; } template - constexpr boolish operator!=(proxy_reference that) const requires CanNEq { + [[nodiscard]] constexpr boolish operator!=(proxy_reference that) const + requires CanNEq { return {ref_ != that.peek()}; } template - constexpr boolish operator<(proxy_reference that) const requires CanLt { + [[nodiscard]] constexpr boolish operator<(proxy_reference that) const requires CanLt { return {ref_ < that.peek()}; } template - constexpr boolish operator>(proxy_reference that) const requires CanGt { + [[nodiscard]] constexpr boolish operator>(proxy_reference that) const requires CanGt { return {ref_ > that.peek()}; } template - constexpr boolish operator<=(proxy_reference that) const requires CanLtE { + [[nodiscard]] constexpr boolish operator<=(proxy_reference that) const + requires CanLtE { return {ref_ <= that.peek()}; } template - constexpr boolish operator>=(proxy_reference that) const requires CanGtE { + [[nodiscard]] constexpr boolish operator>=(proxy_reference that) const + requires CanGtE { return {ref_ >= that.peek()}; } // clang-format off - friend constexpr boolish operator==(proxy_reference r, Value const& val) requires CanEq { + [[nodiscard]] friend constexpr boolish operator==(proxy_reference r, Value const& val) + requires CanEq { return {r.ref_ == val}; } - friend constexpr boolish operator==(Value const& val, proxy_reference r) requires CanEq { + [[nodiscard]] friend constexpr boolish operator==(Value const& val, proxy_reference r) + requires CanEq { return {r.ref_ == val}; } - friend constexpr boolish operator!=(proxy_reference r, Value const& val) requires CanNEq { + [[nodiscard]] friend constexpr boolish operator!=(proxy_reference r, Value const& val) + requires CanNEq { return {r.ref_ != val}; } - friend constexpr boolish operator!=(Value const& val, proxy_reference r) requires CanNEq { + [[nodiscard]] friend constexpr boolish operator!=(Value const& val, proxy_reference r) + requires CanNEq { return {r.ref_ != val}; } - friend constexpr boolish operator<(Value const& val, proxy_reference r) requires CanLt { + [[nodiscard]] friend constexpr boolish operator<(Value const& val, proxy_reference r) + requires CanLt { return {val < r.ref_}; } - friend constexpr boolish operator<(proxy_reference r, Value const& val) requires CanLt { + [[nodiscard]] friend constexpr boolish operator<(proxy_reference r, Value const& val) + requires CanLt { return {r.ref_ < val}; } - friend constexpr boolish operator>(Value const& val, proxy_reference r) requires CanGt { + [[nodiscard]] friend constexpr boolish operator>(Value const& val, proxy_reference r) + requires CanGt { return {val > r.ref_}; } - friend constexpr boolish operator>(proxy_reference r, Value const& val) requires CanGt { + [[nodiscard]] friend constexpr boolish operator>(proxy_reference r, Value const& val) + requires CanGt { return {r.ref_ > val}; } - friend constexpr boolish operator<=(Value const& val, proxy_reference r) requires CanLtE { + [[nodiscard]] friend constexpr boolish operator<=(Value const& val, proxy_reference r) + requires CanLtE { return {val <= r.ref_}; } - friend constexpr boolish operator<=(proxy_reference r, Value const& val) requires CanLtE { + [[nodiscard]] friend constexpr boolish operator<=(proxy_reference r, Value const& val) + requires CanLtE { return {r.ref_ <= val}; } - friend constexpr boolish operator>=(Value const& val, proxy_reference r) requires CanGtE { + [[nodiscard]] friend constexpr boolish operator>=(Value const& val, proxy_reference r) + requires CanGtE { return {val >= r.ref_}; } - friend constexpr boolish operator>=(proxy_reference r, Value const& val) requires CanGtE { + [[nodiscard]] friend constexpr boolish operator>=(proxy_reference r, Value const& val) + requires CanGtE { return {r.ref_ >= val}; } // clang-format on - constexpr Element& peek() const noexcept { + [[nodiscard]] constexpr Element& peek() const noexcept { return ref_; } }; @@ -466,7 +502,8 @@ namespace test { // iterator unwrapping operations: using _Prevent_inheriting_unwrap = iterator; - using unwrap = iterator; + using unwrap = std::conditional_t, Element*, + iterator>; [[nodiscard]] constexpr auto _Unwrapped() const& noexcept requires (to_bool(Wrapped) && to_bool(Eq)) { return unwrap{ptr_}; @@ -479,11 +516,19 @@ namespace test { static constexpr bool _Unwrap_when_unverified = true; constexpr void _Seek_to(unwrap const& i) noexcept requires (to_bool(Wrapped) && to_bool(Eq)) { - ptr_ = i.peek(); + if constexpr (at_least) { + ptr_ = i; + } else { + ptr_ = i.peek(); + } } constexpr void _Seek_to(unwrap&& i) noexcept requires (to_bool(Wrapped)) { - ptr_ = i.peek(); + if constexpr (at_least) { + ptr_ = i; + } else { + ptr_ = i.peek(); + } } }; // clang-format on @@ -570,8 +615,8 @@ namespace test { return elements_.data(); } - using UI = iterator; - using US = conditional_t>; + using UI = typename I::unwrap; + using US = conditional_t>; [[nodiscard]] constexpr UI _Unchecked_begin() const noexcept { if constexpr (!derived_from) { @@ -1003,6 +1048,11 @@ constexpr void test_fwd_fwd() { with_forward_ranges, Element1>::call(); } +template +constexpr void test_bidi_bidi() { + with_bidirectional_ranges, Element1>::call(); +} + template constexpr void test_in_write() { with_input_ranges, Element1>::call(); diff --git a/tests/std/test.lst b/tests/std/test.lst index 4c9d6bf510c..c6f5d5d689b 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -240,6 +240,7 @@ tests\P0896R4_ranges_alg_all_of tests\P0896R4_ranges_alg_any_of tests\P0896R4_ranges_alg_binary_search tests\P0896R4_ranges_alg_copy +tests\P0896R4_ranges_alg_copy_backward tests\P0896R4_ranges_alg_copy_if tests\P0896R4_ranges_alg_copy_n tests\P0896R4_ranges_alg_count diff --git a/tests/std/tests/P0896R4_ranges_alg_copy_backward/env.lst b/tests/std/tests/P0896R4_ranges_alg_copy_backward/env.lst new file mode 100644 index 00000000000..f3ccc8613c6 --- /dev/null +++ b/tests/std/tests/P0896R4_ranges_alg_copy_backward/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_matrix.lst diff --git a/tests/std/tests/P0896R4_ranges_alg_copy_backward/test.cpp b/tests/std/tests/P0896R4_ranges_alg_copy_backward/test.cpp new file mode 100644 index 00000000000..ac89778f756 --- /dev/null +++ b/tests/std/tests/P0896R4_ranges_alg_copy_backward/test.cpp @@ -0,0 +1,104 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +#include + +using namespace std; + +// Validate that copy_backward_result aliases in_out_result +STATIC_ASSERT(same_as, ranges::in_out_result>); + +// Validate dangling story +STATIC_ASSERT(same_as{}, static_cast(nullptr))), + ranges::copy_backward_result>); +STATIC_ASSERT(same_as{}, static_cast(nullptr))), + ranges::copy_backward_result>); + +static constexpr int input[] = {13, 42, 1729}; +static constexpr int expected_overlapping[] = {0, 0, 1, 2}; + +struct instantiator { + template + static constexpr void call() { + // For the second range, we need an iterator to the end; it's expedient to simply ignore ranges with differing + // iterator and sentinel types (i.e., ranges that don't satisfy common_range). + if constexpr (ranges::common_range) { + using ranges::copy_backward, ranges::copy_backward_result, ranges::equal, ranges::iterator_t; + const Bidi1 wrapped_input{input}; + + { // Validate range overload + int output[] = {-2, -2, -2}; + Bidi2 wrapped_output{output}; + auto result = copy_backward(wrapped_input, wrapped_output.end()); + STATIC_ASSERT(same_as, iterator_t>>); + assert(result.in == wrapped_input.end()); + assert(result.out == wrapped_output.begin()); + assert(equal(output, input)); + } + { // Validate iterator + sentinel overload + int output[] = {-2, -2, -2}; + Bidi2 wrapped_output{output}; + auto result = copy_backward(wrapped_input.begin(), wrapped_input.end(), wrapped_output.end()); + STATIC_ASSERT(same_as, iterator_t>>); + assert(result.in == wrapped_input.end()); + assert(result.out == wrapped_output.begin()); + assert(equal(output, input)); + } + { // Validate overlapping ranges + int io[] = {0, 1, 2, 42}; + Bidi1 in{span{io}.first<3>()}; + Bidi2 out{span{io}.last<3>()}; + auto result = copy_backward(in, out.end()); + STATIC_ASSERT(same_as, iterator_t>>); + assert(result.in == in.end()); + assert(result.out == out.begin()); + assert(equal(io, expected_overlapping)); + } + } + } +}; + +constexpr void test_memmove() { + // Get some coverage for the memmove optimization, which we would not otherwise have since we do not currently + // unwrap output iterators. TRANSITION, GH-893 + using ranges::copy_backward, ranges::copy_backward_result, ranges::begin, ranges::end, ranges::equal; + + { // Validate range overload + int output[] = {-2, -2, -2}; + auto result = copy_backward(input, end(output)); + STATIC_ASSERT(same_as>); + assert(result.in == end(input)); + assert(result.out == begin(output)); + assert(equal(output, input)); + } + { // Validate iterator + sentinel overload + int output[] = {-2, -2, -2}; + auto result = copy_backward(begin(input), end(input), end(output)); + STATIC_ASSERT(same_as>); + assert(result.in == end(input)); + assert(result.out == begin(output)); + assert(equal(output, input)); + } + { // Validate overlapping ranges + int io[] = {0, 1, 2, 42}; + auto result = copy_backward(io + 0, io + 3, io + 4); + STATIC_ASSERT(same_as>); + assert(result.in == io + 3); + assert(result.out == io + 1); + assert(equal(io, expected_overlapping)); + } +} + +int main() { + STATIC_ASSERT((test_bidi_bidi(), true)); + test_bidi_bidi(); + + STATIC_ASSERT((test_memmove(), true)); + test_memmove(); +} diff --git a/tests/std/tests/P0896R4_ranges_alg_copy_if/test.cpp b/tests/std/tests/P0896R4_ranges_alg_copy_if/test.cpp index aa257403649..e2793759350 100644 --- a/tests/std/tests/P0896R4_ranges_alg_copy_if/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_copy_if/test.cpp @@ -101,6 +101,8 @@ struct instantiator { }; int main() { +#ifndef _PREFAST_ // TRANSITION, GH-1030 STATIC_ASSERT((test_in_write(), true)); +#endif // TRANSITION, GH-1030 test_in_write(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp b/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp index ac24c5645f2..d938ff02434 100644 --- a/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp @@ -108,11 +108,16 @@ struct make_and_sort_heap_test { ASSERT(!is_heap(wrapped, less{}, get_first)); - make_heap(wrapped, less{}, get_first); - ASSERT(is_heap(wrapped, less{}, get_first)); - - sort_heap(wrapped, less{}, get_first); - ASSERT(is_sorted(wrapped, less{}, get_first)); +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163 + if constexpr (!ranges::contiguous_range) +#endif // TRANSITION, VSO-938163 + { + make_heap(wrapped, less{}, get_first); + ASSERT(is_heap(wrapped, less{}, get_first)); + + sort_heap(wrapped, less{}, get_first); + ASSERT(is_sorted(wrapped, less{}, get_first)); + } } { @@ -121,11 +126,16 @@ struct make_and_sort_heap_test { ASSERT(!is_heap(wrapped.begin(), wrapped.end(), less{}, get_first)); - make_heap(wrapped.begin(), wrapped.end(), less{}, get_first); - ASSERT(is_heap(wrapped.begin(), wrapped.end(), less{}, get_first)); +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163 + if constexpr (!ranges::contiguous_range) +#endif // TRANSITION, VSO-938163 + { + make_heap(wrapped.begin(), wrapped.end(), less{}, get_first); + ASSERT(is_heap(wrapped.begin(), wrapped.end(), less{}, get_first)); - sort_heap(wrapped.begin(), wrapped.end(), less{}, get_first); - ASSERT(is_sorted(wrapped.begin(), wrapped.end(), less{}, get_first)); + sort_heap(wrapped.begin(), wrapped.end(), less{}, get_first); + ASSERT(is_sorted(wrapped.begin(), wrapped.end(), less{}, get_first)); + } } } }; @@ -182,24 +192,34 @@ struct push_and_pop_heap_test { auto buff = initial_values; const Range wrapped{buff}; - pop_heap(wrapped, less{}, get_first); - ASSERT(equal(wrapped, expectedPopped)); +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163 + if constexpr (!ranges::contiguous_range) +#endif // TRANSITION, VSO-938163 + { + pop_heap(wrapped, less{}, get_first); + ASSERT(equal(wrapped, expectedPopped)); - push_heap(wrapped, less{}, get_first); - ASSERT(equal(wrapped, expectedPushed)); + push_heap(wrapped, less{}, get_first); + ASSERT(equal(wrapped, expectedPushed)); + } } { auto buff = initial_values; const Range wrapped{buff}; - pop_heap(wrapped.begin(), wrapped.end(), less{}, get_first); - ASSERT(is_heap(expectedPopped.begin(), expectedPopped.end() - 1, less{}, get_first)); - ASSERT(equal(wrapped.begin(), wrapped.end(), expectedPopped.begin(), expectedPopped.end())); - - push_heap(wrapped.begin(), wrapped.end(), less{}, get_first); - ASSERT(is_heap(expectedPushed, less{}, get_first)); - ASSERT(equal(wrapped.begin(), wrapped.end(), expectedPushed.begin(), expectedPushed.end())); +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163 + if constexpr (!ranges::contiguous_range) +#endif // TRANSITION, VSO-938163 + { + pop_heap(wrapped.begin(), wrapped.end(), less{}, get_first); + ASSERT(is_heap(expectedPopped.begin(), expectedPopped.end() - 1, less{}, get_first)); + ASSERT(equal(wrapped.begin(), wrapped.end(), expectedPopped.begin(), expectedPopped.end())); + + push_heap(wrapped.begin(), wrapped.end(), less{}, get_first); + ASSERT(is_heap(expectedPushed, less{}, get_first)); + ASSERT(equal(wrapped.begin(), wrapped.end(), expectedPushed.begin(), expectedPushed.end())); + } } } }; diff --git a/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp b/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp index 30f7c5e8394..51a0b864436 100644 --- a/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp @@ -71,7 +71,9 @@ constexpr void smoke_test() { } int main() { +#ifndef _PREFAST_ // TRANSITION, GH-1030 STATIC_ASSERT((smoke_test(), true)); +#endif // TRANSITION, GH-1030 smoke_test(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_move/test.cpp b/tests/std/tests/P0896R4_ranges_alg_move/test.cpp index c97f016e4bc..d242beead1e 100644 --- a/tests/std/tests/P0896R4_ranges_alg_move/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_move/test.cpp @@ -36,40 +36,45 @@ struct instantiator { static constexpr int_wrapper expected_output[3] = {13, 55, 12345}; static constexpr int_wrapper expected_input[3] = {-1, -1, -1}; - static constexpr void eq(int_wrapper const (&output)[3], int_wrapper const (&input)[3]) { - // Extracted into a separate function to keep /analyze from exhausting the compiler heap - assert(ranges::equal(output, expected_output)); - assert(ranges::equal(input, expected_input)); - } - template > Write> static constexpr void call() { - using ranges::move, ranges::move_result, ranges::iterator_t; +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-938163 +#pragma warning(suppress : 4127) // conditional expression is constant + if (!ranges::contiguous_range || !is_constant_evaluated()) +#endif // TRANSITION, VSO-938163 { - int_wrapper input[3] = {13, 55, 12345}; - int_wrapper output[3] = {-2, -2, -2}; - Read wrapped_input{input}; + using ranges::move, ranges::move_result, ranges::equal, ranges::iterator_t; + { + int_wrapper input[3] = {13, 55, 12345}; + int_wrapper output[3] = {-2, -2, -2}; + Read wrapped_input{input}; - auto result = move(wrapped_input, Write{output}); - STATIC_ASSERT(same_as, Write>>); - assert(result.in == wrapped_input.end()); - assert(result.out.peek() == output + 3); - eq(output, input); - } - { - int_wrapper input[3] = {13, 55, 12345}; - int_wrapper output[3] = {-2, -2, -2}; - Read wrapped_input{input}; + auto result = move(wrapped_input, Write{output}); + STATIC_ASSERT(same_as, Write>>); + assert(result.in == wrapped_input.end()); + assert(result.out.peek() == output + 3); + assert(equal(output, expected_output)); + assert(equal(input, expected_input)); + } + { + int_wrapper input[3] = {13, 55, 12345}; + int_wrapper output[3] = {-2, -2, -2}; + Read wrapped_input{input}; - auto result = move(wrapped_input.begin(), wrapped_input.end(), Write{output}); - assert(result.in == wrapped_input.end()); - assert(result.out.peek() == output + 3); - eq(output, input); + auto result = move(wrapped_input.begin(), wrapped_input.end(), Write{output}); + STATIC_ASSERT(same_as, Write>>); + assert(result.in == wrapped_input.end()); + assert(result.out.peek() == output + 3); + assert(equal(output, expected_output)); + assert(equal(input, expected_input)); + } } } }; int main() { +#ifndef _PREFAST_ // TRANSITION, GH-1030 STATIC_ASSERT((test_in_write(), true)); +#endif // TRANSITION, GH-1030 test_in_write(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_replace_copy/test.cpp b/tests/std/tests/P0896R4_ranges_alg_replace_copy/test.cpp index 965c5ecd5ac..28a7f6febd9 100644 --- a/tests/std/tests/P0896R4_ranges_alg_replace_copy/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_replace_copy/test.cpp @@ -24,14 +24,9 @@ struct instantiator { static constexpr P input[5] = {{0, 99}, {1, 47}, {2, 99}, {3, 47}, {4, 99}}; static constexpr P expected[5] = {{0, 99}, {47, 1}, {2, 99}, {47, 1}, {4, 99}}; - static constexpr void eq(P const (&output)[5]) { - // Extracted into a separate function to keep /analyze from exhausting the compiler heap - assert(ranges::equal(output, expected)); - } - template > Write> static constexpr void call() { - using ranges::replace_copy, ranges::replace_copy_result, ranges::iterator_t; + using ranges::replace_copy, ranges::replace_copy_result, ranges::equal, ranges::iterator_t; { // Validate iterator + sentinel overload P output[5] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}}; Read wrapped_input{input}; @@ -41,7 +36,7 @@ struct instantiator { STATIC_ASSERT(same_as, Write>>); assert(result.in == wrapped_input.end()); assert(result.out.peek() == output + 5); - eq(output); + assert(equal(output, expected)); } { // Validate range overload P output[5] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}}; @@ -51,12 +46,14 @@ struct instantiator { STATIC_ASSERT(same_as, Write>>); assert(result.in == wrapped_input.end()); assert(result.out.peek() == output + 5); - eq(output); + assert(equal(output, expected)); } } }; int main() { +#ifndef _PREFAST_ // TRANSITION, GH-1030 STATIC_ASSERT((input_range_output_iterator_permutations(), true)); +#endif // TRANSITION, GH-1030 input_range_output_iterator_permutations(); } diff --git a/tests/std/tests/P0896R4_ranges_alg_replace_copy_if/test.cpp b/tests/std/tests/P0896R4_ranges_alg_replace_copy_if/test.cpp index 0048304155c..c3a3860c036 100644 --- a/tests/std/tests/P0896R4_ranges_alg_replace_copy_if/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_replace_copy_if/test.cpp @@ -26,14 +26,9 @@ struct instantiator { static constexpr P input[5] = {{0, 99}, {1, 47}, {2, 99}, {3, 47}, {4, 99}}; static constexpr P expected[5] = {{0, 99}, {47, 1}, {2, 99}, {47, 1}, {4, 99}}; - static constexpr void eq(P const (&output)[5]) { - // Extracted into a separate function to keep /analyze from exhausting the compiler heap - assert(ranges::equal(output, expected)); - } - template > Write> static constexpr void call() { - using ranges::replace_copy_if, ranges::replace_copy_if_result, ranges::iterator_t; + using ranges::replace_copy_if, ranges::replace_copy_if_result, ranges::equal, ranges::iterator_t; { // Validate iterator + sentinel overload P output[5] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}}; Read wrapped_input{input}; @@ -43,7 +38,7 @@ struct instantiator { STATIC_ASSERT(same_as, Write>>); assert(result.in == wrapped_input.end()); assert(result.out.peek() == output + 5); - eq(output); + assert(equal(output, expected)); } { // Validate range overload P output[5] = {{-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}, {-1, -1}}; @@ -53,12 +48,14 @@ struct instantiator { STATIC_ASSERT(same_as, Write>>); assert(result.in == wrapped_input.end()); assert(result.out.peek() == output + 5); - eq(output); + assert(equal(output, expected)); } } }; int main() { +#ifndef _PREFAST_ // TRANSITION, GH-1030 STATIC_ASSERT((input_range_output_iterator_permutations(), true)); +#endif // TRANSITION, GH-1030 input_range_output_iterator_permutations(); } diff --git a/tests/std/tests/P0896R4_ranges_test_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_test_machinery/test.cpp index 29235e1ecaa..ce114438a6f 100644 --- a/tests/std/tests/P0896R4_ranges_test_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_test_machinery/test.cpp @@ -26,9 +26,8 @@ constexpr bool iter_test() { STATIC_ASSERT(!movable || indirectly_writable); - constexpr bool can_write = - derived_from || (derived_from && assignable_from); + constexpr bool can_write = derived_from // + || (derived_from && assignable_from); STATIC_ASSERT(!can_write || output_iterator); STATIC_ASSERT(!derived_from || input_iterator); @@ -44,7 +43,11 @@ constexpr bool iter_test() { STATIC_ASSERT(!to_bool(Eq) || !to_bool(Diff) || sized_sentinel_for); if constexpr (to_bool(Wrapped)) { - STATIC_ASSERT(same_as<_Unwrapped_t, iterator>); + if constexpr (derived_from) { + STATIC_ASSERT(same_as<_Unwrapped_t, Element*>); + } else { + STATIC_ASSERT(same_as<_Unwrapped_t, iterator>); + } STATIC_ASSERT(same_as<_Unwrapped_t, sentinel>); } diff --git a/tests/std/tests/P0898R3_concepts/test.cpp b/tests/std/tests/P0898R3_concepts/test.cpp index 890f0381d2b..80c224e7df3 100644 --- a/tests/std/tests/P0898R3_concepts/test.cpp +++ b/tests/std/tests/P0898R3_concepts/test.cpp @@ -2407,7 +2407,8 @@ namespace test_boolean_testable { struct Archetype { // clang-format off operator bool() const requires (Select != 0); // Archetype<0> is not implicitly convertible to bool - explicit operator bool() const requires (Select < 2); // Archetype<1> is not explicitly convertible to bool (ambiguity) + explicit operator bool() const requires (Select < 2); // Archetype<1> is not explicitly convertible + // to bool (ambiguity) void operator!() const requires (Select == 2); // !Archetype<2> does not model _Boolean_testable_impl // clang-format on }; diff --git a/tests/std/tests/concepts_matrix.lst b/tests/std/tests/concepts_matrix.lst index 37b0a2358be..8414e31b200 100644 --- a/tests/std/tests/concepts_matrix.lst +++ b/tests/std/tests/concepts_matrix.lst @@ -12,12 +12,12 @@ PM_CL="/MDd /D_ITERATOR_DEBUG_LEVEL=0 /permissive- /Zc:wchar_t-" PM_CL="/MDd /D_ITERATOR_DEBUG_LEVEL=1" PM_CL="/MDd /D_ITERATOR_DEBUG_LEVEL=2 /fp:except /Zc:preprocessor" PM_CL="/MT /D_ITERATOR_DEBUG_LEVEL=0 /await" -# PM_CL="/MT /D_ITERATOR_DEBUG_LEVEL=0 /analyze:only" # TRANSITION, GH-1030 +PM_CL="/MT /D_ITERATOR_DEBUG_LEVEL=0 /analyze:only" PM_CL="/MT /D_ITERATOR_DEBUG_LEVEL=1" PM_CL="/MTd /D_ITERATOR_DEBUG_LEVEL=0 /fp:strict" PM_CL="/MTd /D_ITERATOR_DEBUG_LEVEL=1" PM_CL="/MTd /D_ITERATOR_DEBUG_LEVEL=2 /await" -# PM_CL="/MTd /D_ITERATOR_DEBUG_LEVEL=2 /analyze:only" # TRANSITION, GH-1030 +PM_CL="/MTd /D_ITERATOR_DEBUG_LEVEL=2 /analyze:only" PM_CL="/Za /MD /permissive-" PM_CL="/Za /MDd /permissive-" # PM_CL="/BE /c /MD" diff --git a/tests/tr1/include/tspec_random.h b/tests/tr1/include/tspec_random.h index 64c6e6c4b6b..9580a50b323 100644 --- a/tests/tr1/include/tspec_random.h +++ b/tests/tr1/include/tspec_random.h @@ -8,11 +8,12 @@ using namespace std; // COMMON TYPES #define FLIT(x) x -#define TESTR(fun) do_random_test::gen_data(fun##_dist, fun##_vals, fun##_smaller_ok, fun##_larger_ok) #define BINSIZE 100 #define SAMPLESIZE 100000 #define CHI_SQUARED_FAIL_LIMIT 125.0 +#define TESTR(fun) do_random_test::gen_data(fun##_dist, fun##_vals, fun##_smaller_ok, fun##_larger_ok) + typedef struct One_arg { // argument plus return value Float_type arg1; Float_type ans;