186 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// <numeric>10 11// Became constexpr in C++2012// template <InputIterator InIter,13// OutputIterator<auto, const InIter::value_type&> OutIter,14// Callable<auto, const InIter::value_type&, const InIter::value_type&> BinaryOperation>15// requires Constructible<InIter::value_type, InIter::reference>16// && OutputIterator<OutIter, BinaryOperation::result_type>17// && MoveAssignable<InIter::value_type>18// && CopyConstructible<BinaryOperation>19// OutIter20// adjacent_difference(InIter first, InIter last, OutIter result, BinaryOperation binary_op);21 22#include <numeric>23#include <functional>24#include <string>25#include <cassert>26 27#include "test_macros.h"28#include "test_iterators.h"29 30#if TEST_STD_VER > 1731struct rvalue_subtractable32{33 bool correctOperatorUsed = false;34 35 // make sure the predicate is passed an rvalue and an lvalue (so check that the first argument was moved)36 constexpr rvalue_subtractable operator()(rvalue_subtractable const&, rvalue_subtractable&& r) {37 r.correctOperatorUsed = true;38 return std::move(r);39 }40};41 42constexpr rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable& rhs)43{44 rhs.correctOperatorUsed = false;45 return rhs;46}47 48constexpr rvalue_subtractable operator-(rvalue_subtractable const&, rvalue_subtractable&& rhs)49{50 rhs.correctOperatorUsed = true;51 return std::move(rhs);52}53 54constexpr void55test_use_move()56{57 const std::size_t size = 100;58 rvalue_subtractable arr[size];59 rvalue_subtractable res1[size];60 rvalue_subtractable res2[size];61 std::adjacent_difference(arr, arr + size, res1);62 std::adjacent_difference(arr, arr + size, res2, /*predicate=*/rvalue_subtractable());63 // start at 1 because the first element is not moved64 for (unsigned i = 1; i < size; ++i) assert(res1[i].correctOperatorUsed);65 for (unsigned i = 1; i < size; ++i) assert(res2[i].correctOperatorUsed);66}67#endif // TEST_STD_VER > 1768 69TEST_CONSTEXPR_CXX20 void test_string() {70 std::string sa[] = {"a", "b", "c"};71 std::string sr[] = {"a", "ba", "cb"};72 std::string output[3];73 std::adjacent_difference(sa, sa + 3, output, std::plus<std::string>());74 for (unsigned i = 0; i < 3; ++i) assert(output[i] == sr[i]);75}76 77template <class InIter, class OutIter>78TEST_CONSTEXPR_CXX20 void79test()80{81 int ia[] = {15, 10, 6, 3, 1};82 int ir[] = {15, 25, 16, 9, 4};83 const unsigned s = sizeof(ia) / sizeof(ia[0]);84 int ib[s] = {0};85 OutIter r = std::adjacent_difference(InIter(ia), InIter(ia+s), OutIter(ib),86 std::plus<int>());87 assert(base(r) == ib + s);88 for (unsigned i = 0; i < s; ++i)89 assert(ib[i] == ir[i]);90}91 92#if TEST_STD_VER >= 1193 94class Y;95 96class X97{98 int i_;99 100 TEST_CONSTEXPR_CXX20 X& operator=(const X&);101public:102 TEST_CONSTEXPR_CXX20 explicit X(int i) : i_(i) {}103 TEST_CONSTEXPR_CXX20 X(const X& x) : i_(x.i_) {}104 TEST_CONSTEXPR_CXX20 X& operator=(X&& x)105 {106 i_ = x.i_;107 x.i_ = -1;108 return *this;109 }110 111 TEST_CONSTEXPR_CXX20 friend X operator-(const X& x, const X& y) {return X(x.i_ - y.i_);}112 113 friend class Y;114};115 116class Y117{118 int i_;119 120 TEST_CONSTEXPR_CXX20 Y& operator=(const Y&);121public:122 TEST_CONSTEXPR_CXX20 explicit Y(int i) : i_(i) {}123 TEST_CONSTEXPR_CXX20 Y(const Y& y) : i_(y.i_) {}124 TEST_CONSTEXPR_CXX20 void operator=(const X& x) {i_ = x.i_;}125};126 127#endif128 129 130TEST_CONSTEXPR_CXX20 bool131test()132{133 test<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();134 test<cpp17_input_iterator<const int*>, forward_iterator<int*> >();135 test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();136 test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();137 test<cpp17_input_iterator<const int*>, int*>();138 139 test<forward_iterator<const int*>, cpp17_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*>, cpp17_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*>, cpp17_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*, cpp17_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 >= 11164 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#endif168 169#if TEST_STD_VER > 17170 test_use_move();171#endif // TEST_STD_VER > 17172 173 test_string();174 175 return true;176}177 178int main(int, char**)179{180 test();181#if TEST_STD_VER > 17182 static_assert(test());183#endif184 return 0;185}186