On 19/06/19 00:04 +0100, Jonathan Wakely wrote:
On 18/06/19 19:08 +0100, Dietmar Kuehl via libstdc++ wrote:
The first release shipping the parallel algorithms is gcc-9.1.0. Specifically 
std::inclusive_scan() *without* execution policy seems to be missing, though. I 
guess, that’s because it was an add/renamed algorithm. The versions
taking an execution policy are present.

Right.

But as of a few minutes ago (and r272459 in subversion) the versions
without an execution policy are also present, thanks to this patch.

This is a small fix for yesterday's patch. This new test enforces the
standard's current requirement that the function object is called with
lvalues (unless you use move iterators for the range). That's probably
a defect and will be discussed at the next WG21 meeting. If we fix the
standard I'll change this test too.

Tested x86_64-linux, committed to trunk.


commit 4e62418aeb33b851aa8fb454962999e84e82d4b9
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Jun 19 16:16:57 2019 +0100

    Fix value category bugs in std::reduce
    
            * include/std/numeric (reduce(Iter, Iter, T, BinOp)): Fix value
            category used in invocable check.
            (reduce(Iter, Iter, T)): Pass initial value as rvalue.
            * testsuite/26_numerics/reduce/2.cc: New test.

diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric
index 66792506d10..fc2242f3de6 100644
--- a/libstdc++-v3/include/std/numeric
+++ b/libstdc++-v3/include/std/numeric
@@ -246,7 +246,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	   _BinaryOperation __binary_op)
     {
       using value_type = typename iterator_traits<_InputIterator>::value_type;
-      static_assert(is_invocable_r_v<_Tp, _BinaryOperation, _Tp&, _Tp&>);
+      static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>);
       static_assert(is_convertible_v<value_type, _Tp>);
       if constexpr (__is_random_access_iter<_InputIterator>::value)
 	{
@@ -278,7 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _InputIterator, typename _Tp>
     inline _Tp
     reduce(_InputIterator __first, _InputIterator __last, _Tp __init)
-    { return std::reduce(__first, __last, __init, plus<>()); }
+    { return std::reduce(__first, __last, std::move(__init), plus<>()); }
 
   /**
    *  @brief  Calculate reduction of values in a range.
diff --git a/libstdc++-v3/testsuite/26_numerics/reduce/2.cc b/libstdc++-v3/testsuite/26_numerics/reduce/2.cc
new file mode 100644
index 00000000000..adbfaf877bd
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/reduce/2.cc
@@ -0,0 +1,70 @@
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// C++17 29.8.3 [reduce]
+
+#include <numeric>
+#include <iterator>
+#include <testsuite_hooks.h>
+#include <testsuite_iterators.h>
+
+struct T
+{
+  T(int);
+  T(T&&); // MoveConstructible
+  T& operator=(T&&); // not required by the standard, but it needs to be
+  T operator+(const T&) const;
+};
+
+void
+test01()
+{
+  T t[1]{1};
+  std::reduce(t, t+1, T(0));
+
+  using __gnu_test::test_container;
+  using __gnu_test::input_iterator_wrapper;
+  test_container<T, input_iterator_wrapper> con(t);
+  std::reduce(con.begin(), con.end(), T(0));
+}
+
+struct Op
+{
+  T operator()(T&, T&) const&;
+
+  // The standard does *not* require invoking as an rvalue to be supported.
+  T operator()(T&, T&) && = delete;
+
+  // The standard does *not* require rvalue arguments to be supported
+  // (this is almost certainly a defect and should be allowed).
+  T operator()(T&&, T&&) const = delete;
+};
+
+void
+test02()
+{
+  T t[1]{1};
+  std::reduce(t, t+1, T(0), Op());
+
+  using __gnu_test::test_container;
+  using __gnu_test::input_iterator_wrapper;
+  test_container<T, input_iterator_wrapper> con(t);
+  std::reduce(con.begin(), con.end(), T(0), Op());
+}

Reply via email to