]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
libstdc++: Replace incorrect static assertion in std::reduce [PR95833]
authorJonathan Wakely <jwakely@redhat.com>
Fri, 18 Jun 2021 13:46:58 +0000 (14:46 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 18 Jun 2021 13:46:58 +0000 (14:46 +0100)
The standard does not require the iterator's value type to be
convertible to the result type, it only requires that the result of
dereferencing the iterator can be passed to the binary function.

libstdc++-v3/ChangeLog:

PR libstdc++/95833
* include/std/numeric (reduce(Iter, Iter, T, BinaryOp)): Replace
incorrect static_assert with ones matching the 'Mandates'
conditions in the standard.
* testsuite/26_numerics/reduce/95833.cc: New test.

libstdc++-v3/include/std/numeric
libstdc++-v3/testsuite/26_numerics/reduce/95833.cc [new file with mode: 0644]

index f36c1f96b2e5b42498605fb54b863948098f02f0..2ab337a0f3abe9a1560303b82eb6e71f6abc3f64 100644 (file)
@@ -278,9 +278,11 @@ namespace __detail
     reduce(_InputIterator __first, _InputIterator __last, _Tp __init,
           _BinaryOperation __binary_op)
     {
-      using value_type = typename iterator_traits<_InputIterator>::value_type;
+      using __ref = typename iterator_traits<_InputIterator>::reference;
+      static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, __ref>);
+      static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, _Tp&>);
       static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>);
-      static_assert(is_convertible_v<value_type, _Tp>);
+      static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, __ref, __ref>);
       if constexpr (__is_random_access_iter<_InputIterator>::value)
        {
          while ((__last - __first) >= 4)
diff --git a/libstdc++-v3/testsuite/26_numerics/reduce/95833.cc b/libstdc++-v3/testsuite/26_numerics/reduce/95833.cc
new file mode 100644 (file)
index 0000000..cf4644f
--- /dev/null
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++17 } }
+// PR libstdc++/95833 - Incorrect static_assert in std::reduce overload
+
+#include <numeric>
+
+struct A { };
+struct B { };
+
+struct binop
+{
+  template<typename T, typename U>
+    A operator()(T&&, U&&) const { return A{}; }
+};
+
+B b;
+A a = std::reduce(&b, &b + 1, A{}, binop{});