diff options
author | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-03-07 11:54:38 +0100 |
---|---|---|
committer | Tomasz Kamiński <tkaminsk@redhat.com> | 2025-03-14 14:28:29 +0100 |
commit | 5abe571e0276fafcc6eed27c27abb28943e67c6f (patch) | |
tree | 9119ffff9b27d6cb75fa3d5c9d4a15314e2faf18 | |
parent | b673d7b593f63a526a85d56204f1217bc4fbf6a1 (diff) | |
download | gcc-5abe571e0276fafcc6eed27c27abb28943e67c6f.zip gcc-5abe571e0276fafcc6eed27c27abb28943e67c6f.tar.gz gcc-5abe571e0276fafcc6eed27c27abb28943e67c6f.tar.bz2 |
libstdc++: Fix views::zip_transform constraints for empty range pack [PR111138]
Add missing move_constructible && regular_invocable constrains on functor type,
and is_object on functor result type for invocations of views::zip_transform
without range arguments.
PR libstdc++/111138
libstdc++-v3/ChangeLog:
* include/std/ranges (_ZipTransform::operator()):
Create separate overload for calls with empty range pack,
and add move_constructible, regular_invocable and
is_object_v<invoke_result_t<...>>> constraints.
* testsuite/std/ranges/zip_transform/1.cc: New tests
Reviewed-by: Patrick Palka <ppalka@redhat.com>
Jonathan Wakely <jwakely@redhat.com>
Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>
-rw-r--r-- | libstdc++-v3/include/std/ranges | 16 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc | 21 |
2 files changed, 32 insertions, 5 deletions
diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges index ef277b8..34c6f11 100644 --- a/libstdc++-v3/include/std/ranges +++ b/libstdc++-v3/include/std/ranges @@ -5333,15 +5333,21 @@ namespace views::__adaptor struct _ZipTransform { + template<typename _Fp> + requires move_constructible<decay_t<_Fp>> && regular_invocable<decay_t<_Fp>&> + && is_object_v<decay_t<invoke_result_t<decay_t<_Fp>&>>> + constexpr auto + operator() [[nodiscard]] (_Fp&& __f) const + { + return views::empty<decay_t<invoke_result_t<decay_t<_Fp>&>>>; + } + template<typename _Fp, typename... _Ts> - requires (sizeof...(_Ts) == 0) || __detail::__can_zip_transform_view<_Fp, _Ts...> + requires (sizeof...(_Ts) != 0) && __detail::__can_zip_transform_view<_Fp, _Ts...> constexpr auto operator() [[nodiscard]] (_Fp&& __f, _Ts&&... __ts) const { - if constexpr (sizeof...(_Ts) == 0) - return views::empty<decay_t<invoke_result_t<decay_t<_Fp>&>>>; - else - return zip_transform_view(std::forward<_Fp>(__f), std::forward<_Ts>(__ts)...); + return zip_transform_view(std::forward<_Fp>(__f), std::forward<_Ts>(__ts)...); } }; diff --git a/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc b/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc index 20abdcb..9a0ad38 100644 --- a/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc +++ b/libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc @@ -9,6 +9,23 @@ namespace ranges = std::ranges; namespace views = std::views; +template<typename T> +concept can_zip_transform = requires (T t) { + views::zip_transform(std::forward<T>(t)); +}; + +static_assert(!can_zip_transform<int>); + +struct NonMovable { + NonMovable(NonMovable&&) = delete; +}; + +static_assert(!can_zip_transform<NonMovable>); +static_assert(!can_zip_transform<NonMovable&>); + +static_assert(!can_zip_transform<void(*)()>); +static_assert(can_zip_transform<int(&(*)())[3]>); + constexpr bool test01() { @@ -46,6 +63,10 @@ test01() VERIFY( ranges::size(z3) == 3 ); VERIFY( ranges::equal(z3, (int[]){3, 6, 9}) ); + auto z4 = views::zip_transform([] () { return 1; }); + VERIFY( ranges::size(z4) == 0 ); + static_assert( std::same_as<ranges::range_value_t<decltype(z4)>, int> ); + return true; } |