[gcc r15-8057] libstdc++: Fix views::zip_transform constraints for empty range pack [PR111138]
Tomasz Kaminski
tkaminsk@gcc.gnu.org
Fri Mar 14 13:29:50 GMT 2025
https://gcc.gnu.org/g:5abe571e0276fafcc6eed27c27abb28943e67c6f
commit r15-8057-g5abe571e0276fafcc6eed27c27abb28943e67c6f
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date: Fri Mar 7 11:54:38 2025 +0100
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>
Diff:
---
libstdc++-v3/include/std/ranges | 16 +++++++++++-----
.../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 ef277b81bd3c..34c6f113e216 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 20abdcba0f85..9a0ad3814e66 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;
}
More information about the Libstdc++-cvs
mailing list