BillyONeal created this revision.
BillyONeal added reviewers: mclow.lists, EricWF.

- Remove _VSTD use and remove C++03-isms in C++17 tests for transform_reduce.
- Add tests for all the transform_reduce overloads that pass in a move-only 
type.
- Repair missing move in libc++ product code.


Repository:
  rL LLVM

https://reviews.llvm.org/D41372

Files:
  include/numeric
  
test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
  
test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
  
test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp

Index: test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
===================================================================
--- test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
+++ test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init_op_op.pass.cpp
@@ -19,7 +19,9 @@
 
 #include <numeric>
 #include <cassert>
+#include <iterator>
 
+#include "MoveOnly.h"
 #include "test_iterators.h"
 
 template <class Iter1, class Iter2, class T, class Op1, class Op2>
@@ -58,6 +60,16 @@
        decltype(std::transform_reduce(p, p, p, Init{}, std::plus<>(), std::multiplies<>()))> );
 }
 
+void test_move_only_types()
+{
+    MoveOnly ia[] = {{1}, {2}, {3}};
+    MoveOnly ib[] = {{1}, {2}, {3}};
+    assert(14 ==
+        std::transform_reduce(std::begin(ia), std::end(ia), std::begin(ib), MoveOnly{0},
+        [](const MoveOnly& lhs, const MoveOnly& rhs) { return MoveOnly{lhs.get() + rhs.get()}; },
+        [](const MoveOnly& lhs, const MoveOnly& rhs) { return MoveOnly{lhs.get() * rhs.get()}; }).get());
+}
+
 int main()
 {
     test_return_type<char, int>();
@@ -94,4 +106,6 @@
     test<const int*,       unsigned int *>();
     test<      int*, const unsigned int *>();
     test<      int*,       unsigned int *>();
+
+    test_move_only_types();
 }
Index: test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
===================================================================
--- test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
+++ test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_iter_init.pass.cpp
@@ -17,7 +17,9 @@
 
 #include <numeric>
 #include <cassert>
+#include <iterator>
 
+#include "MoveOnly.h"
 #include "test_iterators.h"
 
 template <class Iter1, class Iter2, class T>
@@ -56,6 +58,24 @@
                        decltype(std::transform_reduce(p, p, p, Init{}))> );
 }
 
+inline MoveOnly operator+(const MoveOnly& lhs, const MoveOnly& rhs)
+{
+    return MoveOnly{lhs.get() + rhs.get()};
+}
+
+inline MoveOnly operator*(const MoveOnly& lhs, const MoveOnly& rhs)
+{
+    return MoveOnly{lhs.get() * rhs.get()};
+}
+
+void test_move_only_types()
+{
+    MoveOnly ia[] = {{1}, {2}, {3}};
+    MoveOnly ib[] = {{1}, {2}, {3}};
+    assert(14 ==
+        std::transform_reduce(std::begin(ia), std::end(ia), std::begin(ib), MoveOnly{0}).get());
+}
+
 int main()
 {
     test_return_type<char, int>();
@@ -92,4 +112,6 @@
     test<const int*,       unsigned int *>();
     test<      int*, const unsigned int *>();
     test<      int*,       unsigned int *>();
+
+    test_move_only_types();
 }
Index: test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
===================================================================
--- test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
+++ test/std/numerics/numeric.ops/transform.reduce/transform_reduce_iter_iter_init_bop_uop.pass.cpp
@@ -18,40 +18,26 @@
 
 #include <numeric>
 #include <cassert>
+#include <utility>
+#include <iterator>
 
+#include "MoveOnly.h"
 #include "test_iterators.h"
 
-template <class T = void>
-struct identity : std::unary_function<T, T>
-{
-    constexpr const T& operator()(const T& x) const { return x;}
-};
-
-template <>
-struct identity<void>
+struct identity
 {
     template <class T>
-    constexpr auto operator()(T&& x) const
-    _NOEXCEPT_(noexcept(_VSTD::forward<T>(x)))
-    -> decltype        (_VSTD::forward<T>(x))
-        { return        _VSTD::forward<T>(x); }
+    constexpr decltype(auto) operator()(T&& x) const {
+        return std::forward<T>(x);
+    }
 };
 
-
-template <class T = void>
 struct twice
-{
-    constexpr const T operator()(const T& x) const noexcept { return 2 * x; }
-};
-
-template <>
-struct twice<void>
 {
     template <class T>
-    constexpr auto operator()(const T& x) const
-    _NOEXCEPT_(noexcept(2 * x))
-    -> decltype        (2 * x)
-        { return        2 * x; }
+    constexpr auto operator()(const T& x) const {
+        return 2 * x;
+    }
 };
 
 template <class Iter1, class T, class BOp, class UOp>
@@ -70,31 +56,40 @@
     int ia[]          = {1, 2, 3, 4, 5, 6};
     unsigned sa = sizeof(ia) / sizeof(ia[0]);
 
-    test(Iter(ia), Iter(ia),    0, std::plus<>(),       identity<>(),       0);
-    test(Iter(ia), Iter(ia),    1, std::multiplies<>(), identity<>(),       1);
-    test(Iter(ia), Iter(ia+1),  0, std::multiplies<>(), identity<>(),       0);
-    test(Iter(ia), Iter(ia+1),  2, std::plus<>(),       identity<>(),       3);
-    test(Iter(ia), Iter(ia+2),  0, std::plus<>(),       identity<>(),       3);
-    test(Iter(ia), Iter(ia+2),  3, std::multiplies<>(), identity<>(),       6);
-    test(Iter(ia), Iter(ia+sa), 4, std::multiplies<>(), identity<>(),    2880);
-    test(Iter(ia), Iter(ia+sa), 4, std::plus<>(),       identity<>(),      25);
-
-    test(Iter(ia), Iter(ia),    0, std::plus<>(),       twice<>(),       0);
-    test(Iter(ia), Iter(ia),    1, std::multiplies<>(), twice<>(),       1);
-    test(Iter(ia), Iter(ia+1),  0, std::multiplies<>(), twice<>(),       0);
-    test(Iter(ia), Iter(ia+1),  2, std::plus<>(),       twice<>(),       4);
-    test(Iter(ia), Iter(ia+2),  0, std::plus<>(),       twice<>(),       6);
-    test(Iter(ia), Iter(ia+2),  3, std::multiplies<>(), twice<>(),      24);
-    test(Iter(ia), Iter(ia+sa), 4, std::multiplies<>(), twice<>(),  184320); // 64 * 2880
-    test(Iter(ia), Iter(ia+sa), 4, std::plus<>(),       twice<>(),      46);
+    test(Iter(ia), Iter(ia),    0, std::plus<>(),       identity(),       0);
+    test(Iter(ia), Iter(ia),    1, std::multiplies<>(), identity(),       1);
+    test(Iter(ia), Iter(ia+1),  0, std::multiplies<>(), identity(),       0);
+    test(Iter(ia), Iter(ia+1),  2, std::plus<>(),       identity(),       3);
+    test(Iter(ia), Iter(ia+2),  0, std::plus<>(),       identity(),       3);
+    test(Iter(ia), Iter(ia+2),  3, std::multiplies<>(), identity(),       6);
+    test(Iter(ia), Iter(ia+sa), 4, std::multiplies<>(), identity(),    2880);
+    test(Iter(ia), Iter(ia+sa), 4, std::plus<>(),       identity(),      25);
+
+    test(Iter(ia), Iter(ia),    0, std::plus<>(),       twice(),       0);
+    test(Iter(ia), Iter(ia),    1, std::multiplies<>(), twice(),       1);
+    test(Iter(ia), Iter(ia+1),  0, std::multiplies<>(), twice(),       0);
+    test(Iter(ia), Iter(ia+1),  2, std::plus<>(),       twice(),       4);
+    test(Iter(ia), Iter(ia+2),  0, std::plus<>(),       twice(),       6);
+    test(Iter(ia), Iter(ia+2),  3, std::multiplies<>(), twice(),      24);
+    test(Iter(ia), Iter(ia+sa), 4, std::multiplies<>(), twice(),  184320); // 64 * 2880
+    test(Iter(ia), Iter(ia+sa), 4, std::plus<>(),       twice(),      46);
 }
 
 template <typename T, typename Init>
 void test_return_type()
 {
     T *p = nullptr;
     static_assert( std::is_same_v<Init,
-         decltype(std::transform_reduce(p, p, Init{}, std::plus<>(), identity<>()))> );
+         decltype(std::transform_reduce(p, p, Init{}, std::plus<>(), identity()))> );
+}
+
+void test_move_only_types()
+{
+    MoveOnly ia[] = {{1}, {2}, {3}};
+    assert(60 ==
+        std::transform_reduce(std::begin(ia), std::end(ia), MoveOnly{0},
+        [](const MoveOnly& lhs, const MoveOnly& rhs) { return MoveOnly{lhs.get() + rhs.get()}; },
+        [](const MoveOnly& target) { return MoveOnly{target.get() * 10}; }).get());
 }
 
 int main()
@@ -118,7 +113,9 @@
 //  Make sure the math is done using the correct type
     {
     auto v = {1, 2, 3, 4, 5, 6};
-    unsigned res = std::transform_reduce(v.begin(), v.end(), 1U, std::multiplies<>(), twice<>());
+    unsigned res = std::transform_reduce(v.begin(), v.end(), 1U, std::multiplies<>(), twice());
     assert(res == 46080);       // 6! * 64 will not fit into a char
     }
+
+    test_move_only_types();
 }
Index: include/numeric
===================================================================
--- include/numeric
+++ include/numeric
@@ -51,7 +51,7 @@
     T
     transform_reduce(InputIterator1 first1, InputIterator1 last1,
                      InputIterator2 first2, T init);  // C++17
-                     
+
 template<class InputIterator1, class InputIterator2, class T, class BinaryOperation1, class BinaryOperation2>
     T
     transform_reduce(InputIterator1 first1, InputIterator1 last1,
@@ -75,10 +75,10 @@
     OutputIterator
     exclusive_scan(InputIterator first, InputIterator last,
                    OutputIterator result, T init); // C++17
-                           
+
 template<class InputIterator, class OutputIterator, class T, class BinaryOperation>
     OutputIterator
-    exclusive_scan(InputIterator first, InputIterator last, 
+    exclusive_scan(InputIterator first, InputIterator last,
                    OutputIterator result, T init, BinaryOperation binary_op); // C++17
 
 template<class InputIterator, class OutputIterator>
@@ -108,7 +108,7 @@
 	transform_inclusive_scan(InputIterator first, InputIterator last,
                              OutputIterator result,
                              BinaryOperation binary_op, UnaryOperation unary_op);  // C++17
-                                          
+
 template<class InputIterator, class OutputIterator,
          class BinaryOperation, class UnaryOperation, class T>
 	OutputIterator
@@ -196,7 +196,7 @@
 typename iterator_traits<_InputIterator>::value_type
 reduce(_InputIterator __first, _InputIterator __last)
 {
-    return _VSTD::reduce(__first, __last, 
+    return _VSTD::reduce(__first, __last,
        typename iterator_traits<_InputIterator>::value_type{});
 }
 #endif
@@ -226,15 +226,15 @@
 template <class _InputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
-transform_reduce(_InputIterator __first, _InputIterator __last, 
+transform_reduce(_InputIterator __first, _InputIterator __last,
            _Tp __init,  _BinaryOp __b, _UnaryOp __u)
 {
     for (; __first != __last; ++__first)
         __init = __b(__init, __u(*__first));
     return __init;
 }
 
-template <class _InputIterator1, class _InputIterator2, 
+template <class _InputIterator1, class _InputIterator2,
           class _Tp, class _BinaryOp1, class _BinaryOp2>
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
@@ -249,10 +249,10 @@
 template <class _InputIterator1, class _InputIterator2, class _Tp>
 inline _LIBCPP_INLINE_VISIBILITY
 _Tp
-transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, 
+transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1,
                  _InputIterator2 __first2, _Tp __init)
 {
-    return _VSTD::transform_reduce(__first1, __last1, __first2, __init, 
+    return _VSTD::transform_reduce(__first1, __last1, __first2, _VSTD::move(__init),
                                    _VSTD::plus<>(), _VSTD::multiplies<>());
 }
 #endif
@@ -298,7 +298,7 @@
 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
 inline _LIBCPP_INLINE_VISIBILITY
 _OutputIterator
-exclusive_scan(_InputIterator __first, _InputIterator __last, 
+exclusive_scan(_InputIterator __first, _InputIterator __last,
                _OutputIterator __result, _Tp __init, _BinaryOp __b)
 {
     if (__first != __last)
@@ -318,14 +318,14 @@
 template <class _InputIterator, class _OutputIterator, class _Tp>
 inline _LIBCPP_INLINE_VISIBILITY
 _OutputIterator
-exclusive_scan(_InputIterator __first, _InputIterator __last, 
+exclusive_scan(_InputIterator __first, _InputIterator __last,
                _OutputIterator __result, _Tp __init)
 {
     return _VSTD::exclusive_scan(__first, __last, __result, __init, _VSTD::plus<>());
 }
 
 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp>
-_OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, 
+_OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result, _BinaryOp __b,  _Tp __init)
 {
     for (; __first != __last; ++__first, (void) ++__result) {
@@ -336,7 +336,7 @@
 }
 
 template <class _InputIterator, class _OutputIterator, class _BinaryOp>
-_OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, 
+_OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result, _BinaryOp __b)
 {
     if (__first != __last) {
@@ -350,17 +350,17 @@
 }
 
 template <class _InputIterator, class _OutputIterator>
-_OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last, 
+_OutputIterator inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result)
 {
     return _VSTD::inclusive_scan(__first, __last, __result, std::plus<>());
 }
 
-template <class _InputIterator, class _OutputIterator, class _Tp, 
+template <class _InputIterator, class _OutputIterator, class _Tp,
           class _BinaryOp, class _UnaryOp>
 inline _LIBCPP_INLINE_VISIBILITY
 _OutputIterator
-transform_exclusive_scan(_InputIterator __first, _InputIterator __last, 
+transform_exclusive_scan(_InputIterator __first, _InputIterator __last,
                            _OutputIterator __result, _Tp __init,
                            _BinaryOp __b, _UnaryOp __u)
 {
@@ -379,7 +379,7 @@
 }
 
 template <class _InputIterator, class _OutputIterator, class _Tp, class _BinaryOp, class _UnaryOp>
-_OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 
+_OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
                            _OutputIterator __result, _BinaryOp __b, _UnaryOp __u, _Tp __init)
 {
     for (; __first != __last; ++__first, (void) ++__result) {
@@ -391,16 +391,16 @@
 }
 
 template <class _InputIterator, class _OutputIterator, class _BinaryOp, class _UnaryOp>
-_OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator __last, 
+_OutputIterator transform_inclusive_scan(_InputIterator __first, _InputIterator __last,
                                _OutputIterator __result, _BinaryOp __b, _UnaryOp __u)
 {
     if (__first != __last) {
         typename std::iterator_traits<_InputIterator>::value_type __init = __u(*__first);
         *__result++ = __init;
         if (++__first != __last)
             return _VSTD::transform_inclusive_scan(__first, __last, __result, __b, __u, __init);
         }
-    
+
     return __result;
 }
 #endif
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D41372: [l... Billy Robert O'Neal III via Phabricator via cfe-commits

Reply via email to