1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // <numeric> 10 11 // template <InputIterator InIter, 12 // OutputIterator<auto, const InIter::value_type&> OutIter, 13 // Callable<auto, const InIter::value_type&, const InIter::value_type&> BinaryOperation> 14 // requires Constructible<InIter::value_type, InIter::reference> 15 // && OutputIterator<OutIter, BinaryOperation::result_type> 16 // && MoveAssignable<InIter::value_type> 17 // && CopyConstructible<BinaryOperation> 18 // OutIter 19 // adjacent_difference(InIter first, InIter last, OutIter result, BinaryOperation binary_op); 20 21 #include <numeric> 22 #include <functional> 23 #include <string> 24 #include <cassert> 25 26 #include "test_macros.h" 27 #include "test_iterators.h" 28 29 #if TEST_STD_VER > 17 30 struct rvalue_subtractable 31 { 32 bool correctOperatorUsed = false; 33 34 // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved) 35 rvalue_subtractable operator()(rvalue_subtractable const&, rvalue_subtractable&& r) { 36 r.correctOperatorUsed = true; 37 return std::move(r); 38 } 39 }; 40 41 rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable& rhs) 42 { 43 rhs.correctOperatorUsed = false; 44 return rhs; 45 } 46 47 rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable&& rhs) 48 { 49 rhs.correctOperatorUsed = true; 50 return std::move(rhs); 51 } 52 53 void 54 test_use_move() 55 { 56 const std::size_t size = 100; 57 rvalue_subtractable arr[size]; 58 rvalue_subtractable res1[size]; 59 rvalue_subtractable res2[size]; 60 std::adjacent_difference(arr, arr + size, res1); 61 std::adjacent_difference(arr, arr + size, res2, /*predicate=*/rvalue_subtractable()); 62 // start at 1 because the first element is not moved 63 for (unsigned i = 1; i < size; ++i) assert(res1[i].correctOperatorUsed); 64 for (unsigned i = 1; i < size; ++i) assert(res2[i].correctOperatorUsed); 65 } 66 #endif // TEST_STD_VER > 17 67 68 void 69 test_string() 70 { 71 std::string sa[] = {"a", "b", "c"}; 72 std::string sr[] = {"a", "ba", "cb"}; 73 std::string output[3]; 74 std::adjacent_difference(sa, sa + 3, output, std::plus<std::string>()); 75 for (unsigned i = 0; i < 3; ++i) assert(output[i] == sr[i]); 76 } 77 78 template <class InIter, class OutIter> 79 void 80 test() 81 { 82 int ia[] = {15, 10, 6, 3, 1}; 83 int ir[] = {15, 25, 16, 9, 4}; 84 const unsigned s = sizeof(ia) / sizeof(ia[0]); 85 int ib[s] = {0}; 86 OutIter r = std::adjacent_difference(InIter(ia), InIter(ia+s), OutIter(ib), 87 std::plus<int>()); 88 assert(base(r) == ib + s); 89 for (unsigned i = 0; i < s; ++i) 90 assert(ib[i] == ir[i]); 91 } 92 93 #if TEST_STD_VER >= 11 94 95 class Y; 96 97 class X 98 { 99 int i_; 100 101 X& operator=(const X&); 102 public: 103 explicit X(int i) : i_(i) {} 104 X(const X& x) : i_(x.i_) {} 105 X& operator=(X&& x) 106 { 107 i_ = x.i_; 108 x.i_ = -1; 109 return *this; 110 } 111 112 friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);} 113 114 friend class Y; 115 }; 116 117 class Y 118 { 119 int i_; 120 121 Y& operator=(const Y&); 122 public: 123 explicit Y(int i) : i_(i) {} 124 Y(const Y& y) : i_(y.i_) {} 125 void operator=(const X& x) {i_ = x.i_;} 126 }; 127 128 #endif 129 130 131 int main(int, char**) 132 { 133 test<input_iterator<const int*>, output_iterator<int*> >(); 134 test<input_iterator<const int*>, forward_iterator<int*> >(); 135 test<input_iterator<const int*>, bidirectional_iterator<int*> >(); 136 test<input_iterator<const int*>, random_access_iterator<int*> >(); 137 test<input_iterator<const int*>, int*>(); 138 139 test<forward_iterator<const int*>, output_iterator<int*> >(); 140 test<forward_iterator<const int*>, forward_iterator<int*> >(); 141 test<forward_iterator<const int*>, bidirectional_iterator<int*> >(); 142 test<forward_iterator<const int*>, random_access_iterator<int*> >(); 143 test<forward_iterator<const int*>, int*>(); 144 145 test<bidirectional_iterator<const int*>, output_iterator<int*> >(); 146 test<bidirectional_iterator<const int*>, forward_iterator<int*> >(); 147 test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >(); 148 test<bidirectional_iterator<const int*>, random_access_iterator<int*> >(); 149 test<bidirectional_iterator<const int*>, int*>(); 150 151 test<random_access_iterator<const int*>, output_iterator<int*> >(); 152 test<random_access_iterator<const int*>, forward_iterator<int*> >(); 153 test<random_access_iterator<const int*>, bidirectional_iterator<int*> >(); 154 test<random_access_iterator<const int*>, random_access_iterator<int*> >(); 155 test<random_access_iterator<const int*>, int*>(); 156 157 test<const int*, output_iterator<int*> >(); 158 test<const int*, forward_iterator<int*> >(); 159 test<const int*, bidirectional_iterator<int*> >(); 160 test<const int*, random_access_iterator<int*> >(); 161 test<const int*, int*>(); 162 163 #if TEST_STD_VER >= 11 164 X x[3] = {X(1), X(2), X(3)}; 165 Y y[3] = {Y(1), Y(2), Y(3)}; 166 std::adjacent_difference(x, x+3, y, std::minus<X>()); 167 #endif 168 169 #if TEST_STD_VER > 17 170 test_use_move(); 171 #endif // TEST_STD_VER > 17 172 test_string(); 173 174 return 0; 175 } 176