diff --git a/stl/inc/ranges b/stl/inc/ranges index 7b283ed9f..db45abf8e 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -8370,7 +8370,7 @@ namespace ranges { template _NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(_Rng&&) _CONST_CALL_OPERATOR noexcept - requires (_Nx == 0) + requires (_Nx == 0) && forward_range<_Rng> { return empty_view>{}; } @@ -8706,7 +8706,8 @@ namespace ranges { template _NODISCARD _STATIC_CALL_OPERATOR constexpr auto operator()(_Rng&&, _Fn&& _Func) _CONST_CALL_OPERATOR noexcept(noexcept(views::zip_transform(_STD forward<_Fn>(_Func)))) - requires (_Nx == 0) && requires { views::zip_transform(_STD forward<_Fn>(_Func)); } + requires (_Nx == 0) + && forward_range<_Rng> && requires { views::zip_transform(_STD forward<_Fn>(_Func)); } { return views::zip_transform(_STD forward<_Fn>(_Func)); } diff --git a/tests/std/tests/P2321R2_views_adjacent/test.cpp b/tests/std/tests/P2321R2_views_adjacent/test.cpp index 55e67707f..ac0647a08 100644 --- a/tests/std/tests/P2321R2_views_adjacent/test.cpp +++ b/tests/std/tests/P2321R2_views_adjacent/test.cpp @@ -43,7 +43,7 @@ static_assert(same_as, tuple>); // Check views::pairwise static_assert(same_as)>); -template +template constexpr bool test_one(Rng&& rng, Expected&& expected) { using ranges::adjacent_view, ranges::forward_range, ranges::bidirectional_range, ranges::random_access_range, ranges::sized_range, ranges::common_range, ranges::iterator_t, ranges::sentinel_t, ranges::const_iterator_t, @@ -55,7 +55,6 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { using R = adjacent_view; static_assert(ranges::view); - static_assert(ranges::input_range); static_assert(forward_range); static_assert(bidirectional_range == bidirectional_range); static_assert(random_access_range == random_access_range); @@ -732,7 +731,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { return true; } -template +template constexpr void test_adjacent0(Rng&& rng) { static_assert(!CanConstructAdjacentView); using V = views::all_t; @@ -783,7 +782,7 @@ constexpr void test_adjacent0(Rng&& rng) { } } -template +template requires indirectly_swappable> constexpr void test_iter_swap(Rng& rng) { // This test assumes that 'ranges::size(views::adjacent(rng))' is at least 2 @@ -841,7 +840,7 @@ using test_range = struct instantiator { #ifdef TEST_EVERYTHING - template + template static constexpr void call() { R r{some_ints}; test_one<1>(r, adjacent1_result); @@ -899,6 +898,62 @@ constexpr void instantiation_test() { #endif // TEST_EVERYTHING } +// LWG-4098 views::adjacent<0> should reject non-forward ranges +template +constexpr void test_input_only(Rng&&) { + if constexpr (!ranges::forward_range) { + static_assert(!CanViewAdjacent); + static_assert(!CanViewAdjacent); + static_assert(!CanConstructAdjacentView); + static_assert(!CanConstructAdjacentView); + } + + if constexpr (!ranges::forward_range) { + static_assert(!CanViewAdjacent); + static_assert(!CanViewAdjacent); + static_assert(!CanConstructAdjacentView); + static_assert(!CanConstructAdjacentView); + } +} + +struct input_only_instantiator { +#ifdef TEST_EVERYTHING + template + static constexpr void call() { + R r{some_ints}; + test_input_only<0>(r); + test_input_only<1>(r); + test_input_only<2>(r); + test_input_only<4>(r); + test_input_only<7>(r); + } +#else // ^^^ test all input range permutations / test only "interesting" permutations vvv + template + static constexpr void call() { + test_range r{some_ints}; + test_input_only<0>(r); + test_input_only<1>(r); + test_input_only<2>(r); + test_input_only<4>(r); + test_input_only<7>(r); + } +#endif // TEST_EVERYTHING +}; + +constexpr void instantiation_input_only_test() { +#ifdef TEST_EVERYTHING + test_in(); +#else // ^^^ test all input range permutations / test only "interesting" permutations vvv + using test::Common, test::Sized; + + // The view is sensitive to category, commonality, and size, but oblivious to proxyness and differencing + input_only_instantiator::call(); + input_only_instantiator::call(); + input_only_instantiator::call(); + input_only_instantiator::call(); +#endif // TEST_EVERYTHING +} + template > using move_only_view = test::range}, @@ -939,4 +994,7 @@ int main() { static_assert((instantiation_test(), true)); instantiation_test(); + + static_assert((instantiation_input_only_test(), true)); + instantiation_input_only_test(); } diff --git a/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp b/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp index e9a51c59d..3c78fd8ee 100644 --- a/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp +++ b/tests/std/tests/P2321R2_views_adjacent_transform/test.cpp @@ -73,7 +73,7 @@ using invoke_result_with_repeated_type = invoke_result_with_repeated_type_impl, int, 2>, int>); static_assert(same_as, int, 2>, bool>); -template +template constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { using ranges::adjacent_transform_view, ranges::adjacent_view, ranges::forward_range, ranges::bidirectional_range, ranges::random_access_range, ranges::sized_range, ranges::common_range, ranges::iterator_t, @@ -86,7 +86,6 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { using R = adjacent_transform_view, N>; static_assert(ranges::view); - static_assert(ranges::input_range); static_assert(forward_range); static_assert(bidirectional_range == bidirectional_range); static_assert(random_access_range == random_access_range); @@ -790,7 +789,7 @@ constexpr bool test_one(Rng&& rng, Fn func, Expected&& expected_rng) { return true; } -template +template constexpr void test_adjacent0(Rng&& rng) { auto func = [] { return 602; }; using Fn = decltype(func); @@ -884,7 +883,7 @@ using test_range = test::ProxyRef{!derived_from}>; struct instantiator { - template + template static constexpr void call() { R r{some_ints}; test_one<1>(r, adjacent1_fn, adjacent1_result); @@ -926,6 +925,60 @@ constexpr void instantiation_test() { #endif // TEST_EVERYTHING } +// LWG-4098 views::adjacent<0> should reject non-forward ranges +template +constexpr void test_input_only(Rng&&, Fn&&) { + if constexpr (!ranges::forward_range) { + static_assert(!CanViewAdjacentTransform); + static_assert(!CanViewAdjacentTransform); + } + + if constexpr (!ranges::forward_range) { + static_assert(!CanViewAdjacentTransform); + static_assert(!CanViewAdjacentTransform); + } +} + +struct input_only_instantiator { +#ifdef TEST_EVERYTHING + template + static constexpr void call() { + R r{some_ints}; + auto nullary_fn = [] { return 1729; }; + test_input_only<0>(r, nullary_fn); + test_input_only<1>(r, adjacent1_fn); + test_input_only<2>(r, pairwise_fn); + test_input_only<4>(r, adjacent4_fn); + test_input_only<7>(r, adjacent7_fn); + } +#else // ^^^ test all input range permutations / test only "interesting" permutations vvv + template + static constexpr void call() { + test_range r{some_ints}; + auto nullary_fn = [] { return 1729; }; + test_input_only<0>(r, nullary_fn); + test_input_only<1>(r, adjacent1_fn); + test_input_only<2>(r, pairwise_fn); + test_input_only<4>(r, adjacent4_fn); + test_input_only<7>(r, adjacent7_fn); + } +#endif // TEST_EVERYTHING +}; + +constexpr void instantiation_input_only_test() { +#ifdef TEST_EVERYTHING + test_in(); +#else // ^^^ test all input range permutations / test only "interesting" permutations vvv + using test::Common, test::Sized; + + // The view is sensitive to category, commonality, and size, but oblivious to proxyness and differencing + input_only_instantiator::call(); + input_only_instantiator::call(); + input_only_instantiator::call(); + input_only_instantiator::call(); +#endif // TEST_EVERYTHING +} + template > using move_only_view = test::range}, test::CanView::yes, @@ -988,4 +1041,7 @@ int main() { static_assert((instantiation_test(), true)); instantiation_test(); + + static_assert((instantiation_input_only_test(), true)); + instantiation_input_only_test(); }