diff --git a/stl/inc/ranges b/stl/inc/ranges index 3b90541501f..669adc5d282 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -17,6 +17,7 @@ #include #include #include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -776,6 +777,72 @@ namespace ranges { }; }; + template + class _Range_closure : public _Pipe::_Base<_Range_closure<_Fn, _Types...>> { + public: + // We assume that _Fn is the type of a customization point object. That means + // 1. The behavior of operator() is independent of cvref qualifiers, so we can use `invocable<_Fn, ` without + // loss of generality, and + // 2. _Fn must be default-constructible and stateless, so we can create instances "on-the-fly" and avoid + // storing a copy. + + _STL_INTERNAL_STATIC_ASSERT((same_as, _Types> && ...)); + _STL_INTERNAL_STATIC_ASSERT(is_empty_v<_Fn>&& is_default_constructible_v<_Fn>); + + // clang-format off + template + requires (same_as, _Types> && ...) + constexpr explicit _Range_closure(_UTypes&&... _Args) noexcept( + conjunction_v...>) + : _Captures(_STD forward<_UTypes>(_Args)...) {} + // clang-format on + + void operator()(auto&&) & = delete; + void operator()(auto&&) const& = delete; + void operator()(auto&&) && = delete; + void operator()(auto&&) const&& = delete; + + using _Indices = index_sequence_for<_Types...>; + + template + requires invocable<_Fn, _Ty, _Types&...> + constexpr decltype(auto) operator()(_Ty&& _Arg) & noexcept( + noexcept(_Call(*this, _STD forward<_Ty>(_Arg), _Indices{}))) { + return _Call(*this, _STD forward<_Ty>(_Arg), _Indices{}); + } + + template + requires invocable<_Fn, _Ty, const _Types&...> + constexpr decltype(auto) operator()(_Ty&& _Arg) const& noexcept( + noexcept(_Call(*this, _STD forward<_Ty>(_Arg), _Indices{}))) { + return _Call(*this, _STD forward<_Ty>(_Arg), _Indices{}); + } + + template + requires invocable<_Fn, _Ty, _Types...> + constexpr decltype(auto) operator()(_Ty&& _Arg) && noexcept( + noexcept(_Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}))) { + return _Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}); + } + + template + requires invocable<_Fn, _Ty, const _Types...> + constexpr decltype(auto) operator()(_Ty&& _Arg) const&& noexcept( + noexcept(_Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}))) { + return _Call(_STD move(*this), _STD forward<_Ty>(_Arg), _Indices{}); + } + + private: + template + static constexpr decltype(auto) _Call(_SelfTy&& _Self, _Ty&& _Arg, index_sequence<_Idx...>) noexcept( + noexcept(_Fn{}(_STD forward<_Ty>(_Arg), _STD get<_Idx>(_STD forward<_SelfTy>(_Self)._Captures)...))) { + _STL_INTERNAL_STATIC_ASSERT(same_as, _Indices>); + return _Fn{}(_STD forward<_Ty>(_Arg), _STD get<_Idx>(_STD forward<_SelfTy>(_Self)._Captures)...); + } + + tuple<_Types...> _Captures; + }; + // clang-format off template requires is_object_v<_Ty> @@ -1658,41 +1725,24 @@ namespace ranges { filter_view(_Rng&&, _Pr) -> filter_view, _Pr>; namespace views { - class _Filter_fn { - private: - template - struct _Partial : _Pipe::_Base<_Partial<_Pr>> { - /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred; - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( - noexcept(filter_view(_STD forward<_Rng>(_Range), *_Pred))) requires requires { - filter_view(static_cast<_Rng&&>(_Range), *_Pred); - } - { return filter_view(_STD forward<_Rng>(_Range), *_Pred); } - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( - noexcept(filter_view(_STD forward<_Rng>(_Range), _STD move(*_Pred)))) requires requires { - filter_view(static_cast<_Rng&&>(_Range), _STD move(*_Pred)); - } - { return filter_view(_STD forward<_Rng>(_Range), _STD move(*_Pred)); } - }; - - public: + struct _Filter_fn { // clang-format off template - _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const noexcept(noexcept( - filter_view(_STD forward<_Rng>(_Range), _STD move(_Pred)))) requires requires { - filter_view(static_cast<_Rng&&>(_Range), _STD move(_Pred)); + _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)); } { // clang-format on - return filter_view(_STD forward<_Rng>(_Range), _STD move(_Pred)); + return filter_view(_STD forward<_Rng>(_Range), _STD forward<_Pr>(_Pred)); } - template <_Copy_constructible_object _Pr> - _NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) { - return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}}; + // clang-format off + template + requires constructible_from, _Pr> + _NODISCARD constexpr auto operator()(_Pr&& _Pred) const + noexcept(is_nothrow_constructible_v, _Pr>) { + // clang-format on + return _Range_closure<_Filter_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; @@ -2143,28 +2193,7 @@ namespace ranges { transform_view(_Rng&&, _Fn) -> transform_view, _Fn>; namespace views { - class _Transform_fn { - private: - template - struct _Partial : _Pipe::_Base<_Partial<_Fn>> { - /* [[no_unique_address]] */ _Copyable_box<_Fn> _Fun; - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( - noexcept(transform_view(_STD forward<_Rng>(_Range), *_Fun))) requires requires { - transform_view(static_cast<_Rng&&>(_Range), *_Fun); - } - { return transform_view(_STD forward<_Rng>(_Range), *_Fun); } - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( - noexcept(transform_view(_STD forward<_Rng>(_Range), _STD move(*_Fun)))) requires requires { - transform_view(static_cast<_Rng&&>(_Range), _STD move(*_Fun)); - } - { return transform_view(_STD forward<_Rng>(_Range), _STD move(*_Fun)); } - }; - - public: + struct _Transform_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Fn _Fun) const noexcept(noexcept( @@ -2175,9 +2204,13 @@ namespace ranges { return transform_view(_STD forward<_Rng>(_Range), _STD move(_Fun)); } - template <_Copy_constructible_object _Fn> - _NODISCARD constexpr auto operator()(_Fn _Fun) const noexcept(is_nothrow_move_constructible_v<_Fn>) { - return _Partial<_Fn>{._Fun = {in_place, _STD move(_Fun)}}; + // clang-format off + template + requires constructible_from, _Fn> + _NODISCARD constexpr auto operator()(_Fn&& _Fun) const + noexcept(is_nothrow_constructible_v, _Fn>) { + // clang-format on + return _Range_closure<_Transform_fn, decay_t<_Fn>>{_STD forward<_Fn>(_Fun)}; } }; @@ -2394,51 +2427,6 @@ namespace ranges { template static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); - template - struct _Partial : _Pipe::_Base<_Partial<_Ty>> { - _Ty _Length; - - // clang-format off - template - requires convertible_to<_Ty&, range_difference_t<_Rng>> - _NODISCARD constexpr auto operator()(_Rng&& _Range) & - noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _Length))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Take_fn{}(_STD forward<_Rng>(_Range), _Length); - } - - // clang-format off - template - requires convertible_to> - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& - noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _Length))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Take_fn{}(_STD forward<_Rng>(_Range), _Length); - } - - // clang-format off - template - requires convertible_to<_Ty, range_difference_t<_Rng>> - _NODISCARD constexpr auto operator()(_Rng&& _Range) && - noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)); - } - - // clang-format off - template - requires convertible_to> - _NODISCARD constexpr auto operator()(_Rng&& _Range) const&& - noexcept(noexcept(_Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Take_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)); - } - }; - public: template _NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const @@ -2471,9 +2459,13 @@ namespace ranges { } } - template - _NODISCARD constexpr auto operator()(_Ty _Length) const noexcept { - return _Partial<_Ty>{._Length = _STD move(_Length)}; + // clang-format off + template + requires constructible_from, _Ty> + _NODISCARD constexpr auto operator()(_Ty&& _Length) const + noexcept(is_nothrow_constructible_v, _Ty>) { + // clang-format on + return _Range_closure<_Take_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Length)}; } }; @@ -2627,28 +2619,7 @@ namespace ranges { take_while_view(_Rng&&, _Pr) -> take_while_view, _Pr>; namespace views { - class _Take_while_fn { - private: - template - struct _Partial : _Pipe::_Base<_Partial<_Pr>> { - /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred; - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( - noexcept(take_while_view(_STD forward<_Rng>(_Range), *_Pred))) requires requires { - take_while_view(static_cast<_Rng&&>(_Range), *_Pred); - } - { return take_while_view(_STD forward<_Rng>(_Range), *_Pred); } - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( - noexcept(take_while_view(_STD forward<_Rng>(_Range), _STD move(*_Pred)))) requires requires { - take_while_view(static_cast<_Rng&&>(_Range), _STD move(*_Pred)); - } - { return take_while_view(_STD forward<_Rng>(_Range), _STD move(*_Pred)); } - }; - - public: + struct _Take_while_fn { template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const noexcept(noexcept(take_while_view(_STD forward<_Rng>(_Range), _STD move(_Pred)))) requires requires { @@ -2656,9 +2627,13 @@ namespace ranges { } { return take_while_view(_STD forward<_Rng>(_Range), _STD move(_Pred)); } - template <_Copy_constructible_object _Pr> - _NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) { - return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}}; + // clang-format off + template + requires constructible_from, _Pr> + _NODISCARD constexpr auto operator()(_Pr&& _Pred) const + noexcept(is_nothrow_constructible_v, _Pr>) { + // clang-format on + return _Range_closure<_Take_while_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; @@ -2823,51 +2798,6 @@ namespace ranges { template static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); - template - struct _Partial : _Pipe::_Base<_Partial<_Ty>> { - _Ty _Length; - - // clang-format off - template - requires convertible_to<_Ty&, range_difference_t<_Rng>> - _NODISCARD constexpr auto operator()(_Rng&& _Range) & - noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _Length))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Drop_fn{}(_STD forward<_Rng>(_Range), _Length); - } - - // clang-format off - template - requires convertible_to> - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& - noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _Length))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Drop_fn{}(_STD forward<_Rng>(_Range), _Length); - } - - // clang-format off - template - requires convertible_to<_Ty, range_difference_t<_Rng>> - _NODISCARD constexpr auto operator()(_Rng&& _Range) && - noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)); - } - - // clang-format off - template - requires convertible_to> - _NODISCARD constexpr auto operator()(_Rng&& _Range) const&& - noexcept(noexcept(_Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)))) { - // clang-format on - _STL_INTERNAL_STATIC_ASSERT(is_aggregate_v<_Partial>); - return _Drop_fn{}(_STD forward<_Rng>(_Range), _STD move(_Length)); - } - }; - public: template _NODISCARD constexpr auto operator()(_Rng&& _Range, range_difference_t<_Rng> _Count) const @@ -2901,9 +2831,13 @@ namespace ranges { } } - template - _NODISCARD constexpr auto operator()(_Ty _Length) const noexcept { - return _Partial<_Ty>{._Length = _STD move(_Length)}; + // clang-format off + template + requires constructible_from, _Ty> + _NODISCARD constexpr auto operator()(_Ty&& _Length) const + noexcept(is_nothrow_constructible_v, _Ty>) { + // clang-format on + return _Range_closure<_Drop_fn, decay_t<_Ty>>{_STD forward<_Ty>(_Length)}; } }; @@ -2974,28 +2908,7 @@ namespace ranges { inline constexpr bool enable_borrowed_range> = enable_borrowed_range<_Rng>; namespace views { - class _Drop_while_fn { - private: - template - struct _Partial : _Pipe::_Base<_Partial<_Pr>> { - /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred; - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( - noexcept(drop_while_view(_STD forward<_Rng>(_Range), *_Pred))) requires requires { - drop_while_view(static_cast<_Rng&&>(_Range), *_Pred); - } - { return drop_while_view(_STD forward<_Rng>(_Range), *_Pred); } - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept( - noexcept(drop_while_view(_STD forward<_Rng>(_Range), _STD move(*_Pred)))) requires requires { - drop_while_view(static_cast<_Rng&&>(_Range), _STD move(*_Pred)); - } - { return drop_while_view(_STD forward<_Rng>(_Range), _STD move(*_Pred)); } - }; - - public: + struct _Drop_while_fn { template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pr _Pred) const noexcept(noexcept(drop_while_view(_STD forward<_Rng>(_Range), _STD move(_Pred)))) requires requires { @@ -3003,9 +2916,13 @@ namespace ranges { } { return drop_while_view(_STD forward<_Rng>(_Range), _STD move(_Pred)); } - template <_Copy_constructible_object _Pr> - _NODISCARD constexpr auto operator()(_Pr _Pred) const noexcept(is_nothrow_move_constructible_v<_Pr>) { - return _Partial<_Pr>{._Pred = {in_place, _STD move(_Pred)}}; + // clang-format off + template + requires constructible_from, _Pr> + _NODISCARD constexpr auto operator()(_Pr&& _Pred) const + noexcept(is_nothrow_constructible_v, _Pr>) { + // clang-format on + return _Range_closure<_Drop_while_fn, decay_t<_Pr>>{_STD forward<_Pr>(_Pred)}; } }; @@ -3772,28 +3689,7 @@ namespace ranges { -> lazy_split_view, single_view>>; namespace views { - class _Lazy_split_fn { - private: - template - struct _Partial : _Pipe::_Base<_Partial<_Delim>> { - /* [[no_unique_address]] */ _Delim _Delimiter; - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( - noexcept(lazy_split_view(_STD forward<_Rng>(_Range), _Delimiter))) requires requires { - lazy_split_view(static_cast<_Rng&&>(_Range), _Delimiter); - } - { return lazy_split_view(_STD forward<_Rng>(_Range), _Delimiter); } - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(noexcept( - lazy_split_view(_STD forward<_Rng>(_Range), _STD forward<_Delim>(_Delimiter)))) requires requires { - lazy_split_view(static_cast<_Rng&&>(_Range), static_cast<_Delim&&>(_Delimiter)); - } - { return lazy_split_view(_STD forward<_Rng>(_Range), _STD forward<_Delim>(_Delimiter)); } - }; - - public: + struct _Lazy_split_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pat&& _Pattern) const noexcept(noexcept( @@ -3806,11 +3702,11 @@ namespace ranges { // clang-format off template - requires is_lvalue_reference_v<_Delim> || move_constructible<_Delim> + requires constructible_from, _Delim> _NODISCARD constexpr auto operator()(_Delim&& _Delimiter) const - noexcept(is_lvalue_reference_v<_Delim> || is_nothrow_move_constructible_v<_Delim>) { + noexcept(is_nothrow_constructible_v, _Delim>) { // clang-format on - return _Partial<_Delim>{._Delimiter = _STD forward<_Delim>(_Delimiter)}; + return _Range_closure<_Lazy_split_fn, decay_t<_Delim>>{_STD forward<_Delim>(_Delimiter)}; } }; @@ -3982,28 +3878,7 @@ namespace ranges { split_view(_Rng&&, range_value_t<_Rng>) -> split_view, single_view>>; namespace views { - class _Split_fn { - private: - template - struct _Partial : _Pipe::_Base<_Partial<_Delim>> { - /* [[no_unique_address]] */ _Delim _Delimiter; - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( - noexcept(split_view(_STD forward<_Rng>(_Range), _Delimiter))) requires requires { - split_view(static_cast<_Rng&&>(_Range), _Delimiter); - } - { return split_view(_STD forward<_Rng>(_Range), _Delimiter); } - - template - _NODISCARD constexpr auto operator()(_Rng&& _Range) && noexcept(noexcept( - split_view(_STD forward<_Rng>(_Range), _STD forward<_Delim>(_Delimiter)))) requires requires { - split_view(static_cast<_Rng&&>(_Range), static_cast<_Delim&&>(_Delimiter)); - } - { return split_view(_STD forward<_Rng>(_Range), _STD forward<_Delim>(_Delimiter)); } - }; - - public: + struct _Split_fn { // clang-format off template _NODISCARD constexpr auto operator()(_Rng&& _Range, _Pat&& _Pattern) const noexcept(noexcept( @@ -4016,11 +3891,11 @@ namespace ranges { // clang-format off template - requires is_lvalue_reference_v<_Delim> || move_constructible<_Delim> + requires constructible_from, _Delim> _NODISCARD constexpr auto operator()(_Delim&& _Delimiter) const - noexcept(is_lvalue_reference_v<_Delim> || is_nothrow_move_constructible_v<_Delim>) { + noexcept(is_nothrow_constructible_v, _Delim>) { // clang-format on - return _Partial<_Delim>{._Delimiter = _STD forward<_Delim>(_Delimiter)}; + return _Range_closure<_Split_fn, decay_t<_Delim>>{_STD forward<_Delim>(_Delimiter)}; } }; diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 4d245fd85a6..a50241bf19b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -255,6 +255,7 @@ // P2210R2 Superior String Splitting // P2231R1 Completing constexpr In optional And variant // P2259R1 Repairing Input Range Adaptors And counted_iterator +// P2281R1 Clarifying Range Adaptor Objects // P2325R3 Views Should Not Be Required To Be Default Constructible // P2328R1 join_view Should Join All views Of ranges // P2367R0 Remove Misuses Of List-Initialization From Clause 24 Ranges diff --git a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp index 12c68e5d24d..d43416880a1 100644 --- a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp @@ -1886,6 +1886,48 @@ namespace unwrapped_begin_end { } } // namespace unwrapped_begin_end +namespace closure { + // Verify that range adaptor closures capture with the proper value category + + enum class GLValueKind { lvalue, const_lvalue, xvalue, const_xvalue }; + + template + struct arg { + constexpr arg(arg&) { + static_assert(Allowed == GLValueKind::lvalue); + } + constexpr arg(const arg&) { + static_assert(Allowed == GLValueKind::const_lvalue); + } + constexpr arg(arg&&) { + static_assert(Allowed == GLValueKind::xvalue); + } + constexpr arg(const arg&&) { + static_assert(Allowed == GLValueKind::const_xvalue); + } + + private: + friend void test(); + arg() = default; + }; + + void test() { + using std::as_const, std::move, std::views::filter; + + arg l; + (void) filter(l); + + arg cl; + (void) filter(as_const(cl)); + + arg r; + (void) filter(move(r)); + + arg cr; + (void) filter(move(as_const(cr))); + } +} // namespace closure + int main() { // Validate conditional constexpr STATIC_ASSERT(test_array_ish>()); @@ -1903,4 +1945,6 @@ int main() { STATIC_ASSERT(unwrapped_begin_end::test()); unwrapped_begin_end::test(); + + closure::test(); } diff --git a/tests/std/tests/P0896R4_views_join/test.cpp b/tests/std/tests/P0896R4_views_join/test.cpp index b6cc29fc3f9..9338a8f5003 100644 --- a/tests/std/tests/P0896R4_views_join/test.cpp +++ b/tests/std/tests/P0896R4_views_join/test.cpp @@ -524,7 +524,7 @@ int main() { { // P2328 range of prvalue array static constexpr int result[] = {1, 2, 3, 4, 5}; - auto ToArray = [](const int i) { return array{i + 1}; }; + constexpr auto ToArray = [](const int i) { return array{i + 1}; }; assert(ranges::equal(views::iota(0, 5) | views::transform(ToArray) | views::join, result)); static_assert(ranges::equal(views::iota(0, 5) | views::transform(ToArray) | views::join, result)); } @@ -562,7 +562,7 @@ int main() { } { // Immovable type - auto ToArrayOfImmovable = [](int) { return array{}; }; + constexpr auto ToArrayOfImmovable = [](int) { return array{}; }; assert(ranges::distance(views::iota(0, 2) | views::transform(ToArrayOfImmovable) | views::join) == 6); static_assert(ranges::distance(views::iota(0, 2) | views::transform(ToArrayOfImmovable) | views::join) == 6); } diff --git a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp index 467b1190412..3df03106560 100644 --- a/tests/std/tests/P1502R1_standard_library_header_units/test.cpp +++ b/tests/std/tests/P1502R1_standard_library_header_units/test.cpp @@ -576,12 +576,14 @@ int main() { assert(lcg() == 1043618065); // N4868 [rand.predef]/1 } +#ifndef MSVC_INTERNAL_TESTING // TRANSITION, VSO-1409853 (internal compiler assertion, doesn't affect public releases) { puts("Testing ."); constexpr int arr[]{11, 0, 22, 0, 33, 0, 44, 0, 55}; assert(ranges::distance(views::filter(arr, [](int x) { return x == 0; })) == 4); static_assert(ranges::distance(views::filter(arr, [](int x) { return x != 0; })) == 5); } +#endif // ^^^ no workaround ^^^ { puts("Testing .");