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 // UNSUPPORTED: clang-8 11 // UNSUPPORTED: gcc-9 12 13 // Became constexpr in C++20 14 // template <InputIterator InIter, 15 // OutputIterator<auto, const InIter::value_type&> OutIter, 16 // Callable<auto, const InIter::value_type&, const InIter::value_type&> BinaryOperation> 17 // requires Constructible<InIter::value_type, InIter::reference> 18 // && OutputIterator<OutIter, BinaryOperation::result_type> 19 // && MoveAssignable<InIter::value_type> 20 // && CopyConstructible<BinaryOperation> 21 // OutIter 22 // adjacent_difference(InIter first, InIter last, OutIter result, BinaryOperation binary_op); 23 24 #include <numeric> 25 #include <functional> 26 #include <string> 27 #include <cassert> 28 29 #include "test_macros.h" 30 #include "test_iterators.h" 31 32 #if TEST_STD_VER > 17 33 struct rvalue_subtractable 34 { 35 bool correctOperatorUsed = false; 36 37 // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved) 38 constexpr rvalue_subtractable operator()(rvalue_subtractable const&, rvalue_subtractable&& r) { 39 r.correctOperatorUsed = true; 40 return std::move(r); 41 } 42 }; 43 44 constexpr rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable& rhs) 45 { 46 rhs.correctOperatorUsed = false; 47 return rhs; 48 } 49 50 constexpr rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable&& rhs) 51 { 52 rhs.correctOperatorUsed = true; 53 return std::move(rhs); 54 } 55 56 constexpr void 57 test_use_move() 58 { 59 const std::size_t size = 100; 60 rvalue_subtractable arr[size]; 61 rvalue_subtractable res1[size]; 62 rvalue_subtractable res2[size]; 63 std::adjacent_difference(arr, arr + size, res1); 64 std::adjacent_difference(arr, arr + size, res2, /*predicate=*/rvalue_subtractable()); 65 // start at 1 because the first element is not moved 66 for (unsigned i = 1; i < size; ++i) assert(res1[i].correctOperatorUsed); 67 for (unsigned i = 1; i < size; ++i) assert(res2[i].correctOperatorUsed); 68 } 69 #endif // TEST_STD_VER > 17 70 71 // C++20 can use string in constexpr evaluation, but both libc++ and MSVC 72 // don't have the support yet. In these cases omit the constexpr test. 73 // FIXME Remove constexpr string workaround introduced in D90569 74 #if TEST_STD_VER > 17 && \ 75 (!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L) 76 void 77 #else 78 TEST_CONSTEXPR_CXX20 void 79 #endif 80 test_string() 81 { 82 std::string sa[] = {"a", "b", "c"}; 83 std::string sr[] = {"a", "ba", "cb"}; 84 std::string output[3]; 85 std::adjacent_difference(sa, sa + 3, output, std::plus<std::string>()); 86 for (unsigned i = 0; i < 3; ++i) assert(output[i] == sr[i]); 87 } 88 89 template <class InIter, class OutIter> 90 TEST_CONSTEXPR_CXX20 void 91 test() 92 { 93 int ia[] = {15, 10, 6, 3, 1}; 94 int ir[] = {15, 25, 16, 9, 4}; 95 const unsigned s = sizeof(ia) / sizeof(ia[0]); 96 int ib[s] = {0}; 97 OutIter r = std::adjacent_difference(InIter(ia), InIter(ia+s), OutIter(ib), 98 std::plus<int>()); 99 assert(base(r) == ib + s); 100 for (unsigned i = 0; i < s; ++i) 101 assert(ib[i] == ir[i]); 102 } 103 104 #if TEST_STD_VER >= 11 105 106 class Y; 107 108 class X 109 { 110 int i_; 111 112 TEST_CONSTEXPR_CXX20 X& operator=(const X&); 113 public: 114 TEST_CONSTEXPR_CXX20 explicit X(int i) : i_(i) {} 115 TEST_CONSTEXPR_CXX20 X(const X& x) : i_(x.i_) {} 116 TEST_CONSTEXPR_CXX20 X& operator=(X&& x) 117 { 118 i_ = x.i_; 119 x.i_ = -1; 120 return *this; 121 } 122 123 TEST_CONSTEXPR_CXX20 friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);} 124 125 friend class Y; 126 }; 127 128 class Y 129 { 130 int i_; 131 132 TEST_CONSTEXPR_CXX20 Y& operator=(const Y&); 133 public: 134 TEST_CONSTEXPR_CXX20 explicit Y(int i) : i_(i) {} 135 TEST_CONSTEXPR_CXX20 Y(const Y& y) : i_(y.i_) {} 136 TEST_CONSTEXPR_CXX20 void operator=(const X& x) {i_ = x.i_;} 137 }; 138 139 #endif 140 141 142 TEST_CONSTEXPR_CXX20 bool 143 test() 144 { 145 test<cpp17_input_iterator<const int*>, output_iterator<int*> >(); 146 test<cpp17_input_iterator<const int*>, forward_iterator<int*> >(); 147 test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >(); 148 test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >(); 149 test<cpp17_input_iterator<const int*>, int*>(); 150 151 test<forward_iterator<const int*>, output_iterator<int*> >(); 152 test<forward_iterator<const int*>, forward_iterator<int*> >(); 153 test<forward_iterator<const int*>, bidirectional_iterator<int*> >(); 154 test<forward_iterator<const int*>, random_access_iterator<int*> >(); 155 test<forward_iterator<const int*>, int*>(); 156 157 test<bidirectional_iterator<const int*>, output_iterator<int*> >(); 158 test<bidirectional_iterator<const int*>, forward_iterator<int*> >(); 159 test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >(); 160 test<bidirectional_iterator<const int*>, random_access_iterator<int*> >(); 161 test<bidirectional_iterator<const int*>, int*>(); 162 163 test<random_access_iterator<const int*>, output_iterator<int*> >(); 164 test<random_access_iterator<const int*>, forward_iterator<int*> >(); 165 test<random_access_iterator<const int*>, bidirectional_iterator<int*> >(); 166 test<random_access_iterator<const int*>, random_access_iterator<int*> >(); 167 test<random_access_iterator<const int*>, int*>(); 168 169 test<const int*, output_iterator<int*> >(); 170 test<const int*, forward_iterator<int*> >(); 171 test<const int*, bidirectional_iterator<int*> >(); 172 test<const int*, random_access_iterator<int*> >(); 173 test<const int*, int*>(); 174 175 #if TEST_STD_VER >= 11 176 X x[3] = {X(1), X(2), X(3)}; 177 Y y[3] = {Y(1), Y(2), Y(3)}; 178 std::adjacent_difference(x, x+3, y, std::minus<X>()); 179 #endif 180 181 #if TEST_STD_VER > 17 182 test_use_move(); 183 #endif // TEST_STD_VER > 17 184 // C++20 can use string in constexpr evaluation, but both libc++ and MSVC 185 // don't have the support yet. In these cases omit the constexpr test. 186 // FIXME Remove constexpr string workaround introduced in D90569 187 #if TEST_STD_VER > 17 && \ 188 (!defined(__cpp_lib_constexpr_string) || __cpp_lib_constexpr_string < 201907L) 189 if (!std::is_constant_evaluated()) 190 #endif 191 test_string(); 192 193 return true; 194 } 195 196 int main(int, char**) 197 { 198 test(); 199 #if TEST_STD_VER > 17 200 static_assert(test()); 201 #endif 202 return 0; 203 } 204