From 74fda2dc9f6198c23da01303a51d06ff69008e31 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 19 Jun 2019 16:29:49 +0100 Subject: [PATCH] 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. From-SVN: r272477 --- libstdc++-v3/ChangeLog | 7 +++ libstdc++-v3/include/std/numeric | 4 +- libstdc++-v3/testsuite/26_numerics/reduce/2.cc | 70 ++++++++++++++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/26_numerics/reduce/2.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5702523..e6373ca 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2019-06-19 Jonathan Wakely + + * 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. + 2019-06-18 Jonathan Wakely * include/bits/algorithmfwd.h: Change title of doc group. diff --git a/libstdc++-v3/include/std/numeric b/libstdc++-v3/include/std/numeric index 6679250..fc2242f 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); if constexpr (__is_random_access_iter<_InputIterator>::value) { @@ -278,7 +278,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template 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 0000000..adbfaf8 --- /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 +// . + +// C++17 29.8.3 [reduce] + +#include +#include +#include +#include + +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 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 con(t); + std::reduce(con.begin(), con.end(), T(0), Op()); +} -- 2.7.4