]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Fix views::zip_transform constraints for empty range pack [PR111138]
authorTomasz Kamiński <tkaminsk@redhat.com>
Fri, 7 Mar 2025 10:54:38 +0000 (11:54 +0100)
committerTomasz Kamiński <tkaminsk@redhat.com>
Fri, 14 Mar 2025 13:28:29 +0000 (14:28 +0100)
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>
libstdc++-v3/include/std/ranges
libstdc++-v3/testsuite/std/ranges/zip_transform/1.cc

index ef277b81bd3c10344d1c74dbd36ecc23272c34b0..34c6f113e216db17ba80f69e1f3863d2989dc12d 100644 (file)
@@ -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)...);
        }
     };
 
index 20abdcba0f855715854aa8106ca357eb61b7dd95..9a0ad3814e665d97841a0e544b6d6432af582e58 100644 (file)
@@ -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;
 }