diff --git a/stl/inc/ranges b/stl/inc/ranges index 1da7e9466f..8fffa82ac9 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -8582,6 +8582,10 @@ namespace ranges { _EXPORT_STD inline constexpr _Zip_fn zip{}; } // namespace views + template + concept _Can_const_iterate_zip_transform_view = + range> && regular_invocable...>; + _EXPORT_STD template requires _Zip_transform_constraints<_Func, _ViewTypes...> class zip_transform_view : public view_interface> { @@ -8833,9 +8837,6 @@ namespace ranges { } } - static constexpr bool _Enable_const_begin_end = - (range && regular_invocable...>); - public: zip_transform_view() = default; @@ -8849,7 +8850,7 @@ namespace ranges { } _NODISCARD constexpr auto begin() const noexcept(noexcept(_Iterator{*this, _Zip.begin()})) // strengthened - requires _Enable_const_begin_end + requires _Can_const_iterate_zip_transform_view<_Func, _ViewTypes...> { return _Iterator{*this, _Zip.begin()}; } @@ -8863,7 +8864,7 @@ namespace ranges { } _NODISCARD constexpr auto end() const noexcept(_Is_end_noexcept()) // strengthened - requires _Enable_const_begin_end + requires _Can_const_iterate_zip_transform_view<_Func, _ViewTypes...> { if constexpr (common_range) { return _Iterator{*this, _Zip.end()}; diff --git a/tests/std/tests/P2321R2_views_zip_transform/test.cpp b/tests/std/tests/P2321R2_views_zip_transform/test.cpp index 387283a3e8..64a17e6130 100644 --- a/tests/std/tests/P2321R2_views_zip_transform/test.cpp +++ b/tests/std/tests/P2321R2_views_zip_transform/test.cpp @@ -806,6 +806,20 @@ constexpr bool validate_empty_ranges() { return true; } +// Also test GH-4414: ": zip_transform does not accept non const iterable ranges" +constexpr bool test_gh_4414() { + auto evens_and_odds = views::zip_transform([](int even, int odd) { return even + odd; }, + views::iota(0, 10) | views::filter([](int i) { return i % 2 == 0; }), + views::iota(0, 10) | views::filter([](int i) { return i % 2 != 0; })); + + using ZippedTransformed = decltype(evens_and_odds); + STATIC_ASSERT(ranges::range); + STATIC_ASSERT(!ranges::range); + + constexpr int expected_results[]{1, 5, 9, 13, 17}; + return ranges::equal(expected_results, evens_and_odds); +} + int main() { // Empty RangeTypes... parameter pack { @@ -858,6 +872,10 @@ int main() { test_one(three_element_transform_closure, three_range_transform_results_array, test_element_array_one, test_element_array_two, test_element_array_three); } + { + STATIC_ASSERT(test_gh_4414()); + assert(test_gh_4414()); + } return 0; }