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 // <algorithm> 10 11 // template<InputIterator InIter, class OutIter> 12 // requires OutputIterator<OutIter, RvalueOf<InIter::value_type>::type> 13 // && EqualityComparable<InIter::value_type> 14 // && HasAssign<InIter::value_type, InIter::reference> 15 // && Constructible<InIter::value_type, InIter::reference> 16 // constexpr OutIter // constexpr after C++17 17 // unique_copy(InIter first, InIter last, OutIter result); 18 19 #include <algorithm> 20 #include <cassert> 21 22 #include "MoveOnly.h" 23 #include "test_macros.h" 24 #include "test_iterators.h" 25 26 struct AssignableFromMoveOnly { 27 AssignableFromMoveOnly(int i) : data(i) {} 28 AssignableFromMoveOnly() : data(0) {} 29 int data; 30 AssignableFromMoveOnly& operator=(MoveOnly const& m) { 31 data = m.get(); 32 return *this; 33 } 34 bool operator==(AssignableFromMoveOnly const& rhs) const { return data == rhs.data; } 35 }; 36 37 #if TEST_STD_VER > 17 38 TEST_CONSTEXPR bool test_constexpr() { 39 int ia[] = {0, 1, 2, 2, 4}; 40 int ib[] = {0, 0, 0, 0, 0}; 41 const int expected[] = {0, 1, 2, 4}; 42 43 auto it = std::unique_copy(std::begin(ia), std::end(ia), std::begin(ib)); 44 return it == (std::begin(ib) + std::size(expected)) 45 && *it == 0 // don't overwrite final value in output 46 && std::equal(std::begin(ib), it, std::begin(expected), std::end(expected)) 47 ; 48 } 49 #endif 50 51 template <class InIter, class OutIter> 52 void 53 test() 54 { 55 const int ia[] = {0}; 56 const unsigned sa = sizeof(ia)/sizeof(ia[0]); 57 int ja[sa] = {-1}; 58 OutIter r = std::unique_copy(InIter(ia), InIter(ia+sa), OutIter(ja)); 59 assert(base(r) == ja + sa); 60 assert(ja[0] == 0); 61 62 const int ib[] = {0, 1}; 63 const unsigned sb = sizeof(ib)/sizeof(ib[0]); 64 int jb[sb] = {-1}; 65 r = std::unique_copy(InIter(ib), InIter(ib+sb), OutIter(jb)); 66 assert(base(r) == jb + sb); 67 assert(jb[0] == 0); 68 assert(jb[1] == 1); 69 70 const int ic[] = {0, 0}; 71 const unsigned sc = sizeof(ic)/sizeof(ic[0]); 72 int jc[sc] = {-1}; 73 r = std::unique_copy(InIter(ic), InIter(ic+sc), OutIter(jc)); 74 assert(base(r) == jc + 1); 75 assert(jc[0] == 0); 76 77 const int id[] = {0, 0, 1}; 78 const unsigned sd = sizeof(id)/sizeof(id[0]); 79 int jd[sd] = {-1}; 80 r = std::unique_copy(InIter(id), InIter(id+sd), OutIter(jd)); 81 assert(base(r) == jd + 2); 82 assert(jd[0] == 0); 83 assert(jd[1] == 1); 84 85 const int ie[] = {0, 0, 1, 0}; 86 const unsigned se = sizeof(ie)/sizeof(ie[0]); 87 int je[se] = {-1}; 88 r = std::unique_copy(InIter(ie), InIter(ie+se), OutIter(je)); 89 assert(base(r) == je + 3); 90 assert(je[0] == 0); 91 assert(je[1] == 1); 92 assert(je[2] == 0); 93 94 const int ig[] = {0, 0, 1, 1}; 95 const unsigned sg = sizeof(ig)/sizeof(ig[0]); 96 int jg[sg] = {-1}; 97 r = std::unique_copy(InIter(ig), InIter(ig+sg), OutIter(jg)); 98 assert(base(r) == jg + 2); 99 assert(jg[0] == 0); 100 assert(jg[1] == 1); 101 102 const int ih[] = {0, 1, 1}; 103 const unsigned sh = sizeof(ih)/sizeof(ih[0]); 104 int jh[sh] = {-1}; 105 r = std::unique_copy(InIter(ih), InIter(ih+sh), OutIter(jh)); 106 assert(base(r) == jh + 2); 107 assert(jh[0] == 0); 108 assert(jh[1] == 1); 109 110 const int ii[] = {0, 1, 1, 1, 2, 2, 2}; 111 const unsigned si = sizeof(ii)/sizeof(ii[0]); 112 int ji[si] = {-1}; 113 r = std::unique_copy(InIter(ii), InIter(ii+si), OutIter(ji)); 114 assert(base(r) == ji + 3); 115 assert(ji[0] == 0); 116 assert(ji[1] == 1); 117 assert(ji[2] == 2); 118 } 119 120 int main(int, char**) 121 { 122 test<cpp17_input_iterator<const int*>, cpp17_input_iterator<int*> >(); 123 test<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >(); 124 test<cpp17_input_iterator<const int*>, forward_iterator<int*> >(); 125 test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >(); 126 test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >(); 127 test<cpp17_input_iterator<const int*>, int*>(); 128 129 test<forward_iterator<const int*>, cpp17_output_iterator<int*> >(); 130 test<forward_iterator<const int*>, forward_iterator<int*> >(); 131 test<forward_iterator<const int*>, bidirectional_iterator<int*> >(); 132 test<forward_iterator<const int*>, random_access_iterator<int*> >(); 133 test<forward_iterator<const int*>, int*>(); 134 135 test<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >(); 136 test<bidirectional_iterator<const int*>, forward_iterator<int*> >(); 137 test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >(); 138 test<bidirectional_iterator<const int*>, random_access_iterator<int*> >(); 139 test<bidirectional_iterator<const int*>, int*>(); 140 141 test<random_access_iterator<const int*>, cpp17_output_iterator<int*> >(); 142 test<random_access_iterator<const int*>, forward_iterator<int*> >(); 143 test<random_access_iterator<const int*>, bidirectional_iterator<int*> >(); 144 test<random_access_iterator<const int*>, random_access_iterator<int*> >(); 145 test<random_access_iterator<const int*>, int*>(); 146 147 test<const int*, cpp17_output_iterator<int*> >(); 148 test<const int*, forward_iterator<int*> >(); 149 test<const int*, bidirectional_iterator<int*> >(); 150 test<const int*, random_access_iterator<int*> >(); 151 test<const int*, int*>(); 152 153 // Move only inputs 154 { 155 MoveOnly in[5] = {1, 3, 3, 3, 1}; 156 AssignableFromMoveOnly out[3] = {}; 157 auto result = std::unique_copy(in, in + 5, out); 158 AssignableFromMoveOnly expected[3] = {1, 3, 1}; 159 assert(std::equal(out, out + 3, expected)); 160 assert(result == out + 3); 161 } 162 163 #if TEST_STD_VER > 17 164 static_assert(test_constexpr()); 165 #endif 166 167 return 0; 168 } 169