15a83710eSEric Fiselier //===----------------------------------------------------------------------===//
25a83710eSEric Fiselier //
357b08b09SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
457b08b09SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
557b08b09SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a83710eSEric Fiselier //
75a83710eSEric Fiselier //===----------------------------------------------------------------------===//
85a83710eSEric Fiselier 
95a83710eSEric Fiselier // <algorithm>
105a83710eSEric Fiselier 
115a83710eSEric Fiselier // template<InputIterator InIter, class OutIter>
125a83710eSEric Fiselier //   requires OutputIterator<OutIter, RvalueOf<InIter::value_type>::type>
135a83710eSEric Fiselier //         && EqualityComparable<InIter::value_type>
145a83710eSEric Fiselier //         && HasAssign<InIter::value_type, InIter::reference>
155a83710eSEric Fiselier //         && Constructible<InIter::value_type, InIter::reference>
164bfb9313SMarshall Clow //   constexpr OutIter        // constexpr after C++17
175a83710eSEric Fiselier //   unique_copy(InIter first, InIter last, OutIter result);
185a83710eSEric Fiselier 
195a83710eSEric Fiselier #include <algorithm>
205a83710eSEric Fiselier #include <cassert>
215a83710eSEric Fiselier 
22*62f1e663SHui Xie #include "MoveOnly.h"
234bfb9313SMarshall Clow #include "test_macros.h"
245a83710eSEric Fiselier #include "test_iterators.h"
255a83710eSEric Fiselier 
26*62f1e663SHui Xie struct AssignableFromMoveOnly {
AssignableFromMoveOnlyAssignableFromMoveOnly27*62f1e663SHui Xie   AssignableFromMoveOnly(int i) : data(i) {}
AssignableFromMoveOnlyAssignableFromMoveOnly28*62f1e663SHui Xie   AssignableFromMoveOnly() : data(0) {}
29*62f1e663SHui Xie   int data;
operator =AssignableFromMoveOnly30*62f1e663SHui Xie   AssignableFromMoveOnly& operator=(MoveOnly const& m) {
31*62f1e663SHui Xie     data = m.get();
32*62f1e663SHui Xie     return *this;
33*62f1e663SHui Xie   }
operator ==AssignableFromMoveOnly34*62f1e663SHui Xie   bool operator==(AssignableFromMoveOnly const& rhs) const { return data == rhs.data; }
35*62f1e663SHui Xie };
36*62f1e663SHui Xie 
374bfb9313SMarshall Clow #if TEST_STD_VER > 17
test_constexpr()384bfb9313SMarshall Clow TEST_CONSTEXPR bool test_constexpr() {
394bfb9313SMarshall Clow           int ia[]       = {0, 1, 2, 2, 4};
404bfb9313SMarshall Clow           int ib[]       = {0, 0, 0, 0, 0};
414bfb9313SMarshall Clow     const int expected[] = {0, 1, 2, 4};
424bfb9313SMarshall Clow 
434bfb9313SMarshall Clow     auto it = std::unique_copy(std::begin(ia), std::end(ia), std::begin(ib));
444bfb9313SMarshall Clow     return it == (std::begin(ib) + std::size(expected))
454bfb9313SMarshall Clow         && *it == 0 // don't overwrite final value in output
464bfb9313SMarshall Clow         && std::equal(std::begin(ib), it, std::begin(expected), std::end(expected))
474bfb9313SMarshall Clow         ;
484bfb9313SMarshall Clow     }
494bfb9313SMarshall Clow #endif
504bfb9313SMarshall Clow 
515a83710eSEric Fiselier template <class InIter, class OutIter>
525a83710eSEric Fiselier void
test()535a83710eSEric Fiselier test()
545a83710eSEric Fiselier {
555a83710eSEric Fiselier     const int ia[] = {0};
565a83710eSEric Fiselier     const unsigned sa = sizeof(ia)/sizeof(ia[0]);
575a83710eSEric Fiselier     int ja[sa] = {-1};
585a83710eSEric Fiselier     OutIter r = std::unique_copy(InIter(ia), InIter(ia+sa), OutIter(ja));
595a83710eSEric Fiselier     assert(base(r) == ja + sa);
605a83710eSEric Fiselier     assert(ja[0] == 0);
615a83710eSEric Fiselier 
625a83710eSEric Fiselier     const int ib[] = {0, 1};
635a83710eSEric Fiselier     const unsigned sb = sizeof(ib)/sizeof(ib[0]);
645a83710eSEric Fiselier     int jb[sb] = {-1};
655a83710eSEric Fiselier     r = std::unique_copy(InIter(ib), InIter(ib+sb), OutIter(jb));
665a83710eSEric Fiselier     assert(base(r) == jb + sb);
675a83710eSEric Fiselier     assert(jb[0] == 0);
685a83710eSEric Fiselier     assert(jb[1] == 1);
695a83710eSEric Fiselier 
705a83710eSEric Fiselier     const int ic[] = {0, 0};
715a83710eSEric Fiselier     const unsigned sc = sizeof(ic)/sizeof(ic[0]);
725a83710eSEric Fiselier     int jc[sc] = {-1};
735a83710eSEric Fiselier     r = std::unique_copy(InIter(ic), InIter(ic+sc), OutIter(jc));
745a83710eSEric Fiselier     assert(base(r) == jc + 1);
755a83710eSEric Fiselier     assert(jc[0] == 0);
765a83710eSEric Fiselier 
775a83710eSEric Fiselier     const int id[] = {0, 0, 1};
785a83710eSEric Fiselier     const unsigned sd = sizeof(id)/sizeof(id[0]);
795a83710eSEric Fiselier     int jd[sd] = {-1};
805a83710eSEric Fiselier     r = std::unique_copy(InIter(id), InIter(id+sd), OutIter(jd));
815a83710eSEric Fiselier     assert(base(r) == jd + 2);
825a83710eSEric Fiselier     assert(jd[0] == 0);
835a83710eSEric Fiselier     assert(jd[1] == 1);
845a83710eSEric Fiselier 
855a83710eSEric Fiselier     const int ie[] = {0, 0, 1, 0};
865a83710eSEric Fiselier     const unsigned se = sizeof(ie)/sizeof(ie[0]);
875a83710eSEric Fiselier     int je[se] = {-1};
885a83710eSEric Fiselier     r = std::unique_copy(InIter(ie), InIter(ie+se), OutIter(je));
895a83710eSEric Fiselier     assert(base(r) == je + 3);
905a83710eSEric Fiselier     assert(je[0] == 0);
915a83710eSEric Fiselier     assert(je[1] == 1);
925a83710eSEric Fiselier     assert(je[2] == 0);
935a83710eSEric Fiselier 
945a83710eSEric Fiselier     const int ig[] = {0, 0, 1, 1};
955a83710eSEric Fiselier     const unsigned sg = sizeof(ig)/sizeof(ig[0]);
965a83710eSEric Fiselier     int jg[sg] = {-1};
975a83710eSEric Fiselier     r = std::unique_copy(InIter(ig), InIter(ig+sg), OutIter(jg));
985a83710eSEric Fiselier     assert(base(r) == jg + 2);
995a83710eSEric Fiselier     assert(jg[0] == 0);
1005a83710eSEric Fiselier     assert(jg[1] == 1);
1015a83710eSEric Fiselier 
1025a83710eSEric Fiselier     const int ih[] = {0, 1, 1};
1035a83710eSEric Fiselier     const unsigned sh = sizeof(ih)/sizeof(ih[0]);
1045a83710eSEric Fiselier     int jh[sh] = {-1};
1055a83710eSEric Fiselier     r = std::unique_copy(InIter(ih), InIter(ih+sh), OutIter(jh));
1065a83710eSEric Fiselier     assert(base(r) == jh + 2);
1075a83710eSEric Fiselier     assert(jh[0] == 0);
1085a83710eSEric Fiselier     assert(jh[1] == 1);
1095a83710eSEric Fiselier 
1105a83710eSEric Fiselier     const int ii[] = {0, 1, 1, 1, 2, 2, 2};
1115a83710eSEric Fiselier     const unsigned si = sizeof(ii)/sizeof(ii[0]);
1125a83710eSEric Fiselier     int ji[si] = {-1};
1135a83710eSEric Fiselier     r = std::unique_copy(InIter(ii), InIter(ii+si), OutIter(ji));
1145a83710eSEric Fiselier     assert(base(r) == ji + 3);
1155a83710eSEric Fiselier     assert(ji[0] == 0);
1165a83710eSEric Fiselier     assert(ji[1] == 1);
1175a83710eSEric Fiselier     assert(ji[2] == 2);
1185a83710eSEric Fiselier }
1195a83710eSEric Fiselier 
main(int,char **)1202df59c50SJF Bastien int main(int, char**)
1215a83710eSEric Fiselier {
122*62f1e663SHui Xie     test<cpp17_input_iterator<const int*>, cpp17_input_iterator<int*> >();
1235e97d37bSMark de Wever     test<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
124773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
125773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
126773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
127773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, int*>();
1285a83710eSEric Fiselier 
1295e97d37bSMark de Wever     test<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
1305a83710eSEric Fiselier     test<forward_iterator<const int*>, forward_iterator<int*> >();
1315a83710eSEric Fiselier     test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
1325a83710eSEric Fiselier     test<forward_iterator<const int*>, random_access_iterator<int*> >();
1335a83710eSEric Fiselier     test<forward_iterator<const int*>, int*>();
1345a83710eSEric Fiselier 
1355e97d37bSMark de Wever     test<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
1365a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
1375a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
1385a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
1395a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, int*>();
1405a83710eSEric Fiselier 
1415e97d37bSMark de Wever     test<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
1425a83710eSEric Fiselier     test<random_access_iterator<const int*>, forward_iterator<int*> >();
1435a83710eSEric Fiselier     test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
1445a83710eSEric Fiselier     test<random_access_iterator<const int*>, random_access_iterator<int*> >();
1455a83710eSEric Fiselier     test<random_access_iterator<const int*>, int*>();
1465a83710eSEric Fiselier 
1475e97d37bSMark de Wever     test<const int*, cpp17_output_iterator<int*> >();
1485a83710eSEric Fiselier     test<const int*, forward_iterator<int*> >();
1495a83710eSEric Fiselier     test<const int*, bidirectional_iterator<int*> >();
1505a83710eSEric Fiselier     test<const int*, random_access_iterator<int*> >();
1515a83710eSEric Fiselier     test<const int*, int*>();
1524bfb9313SMarshall Clow 
153*62f1e663SHui Xie     // Move only inputs
154*62f1e663SHui Xie     {
155*62f1e663SHui Xie       MoveOnly in[5]                     = {1, 3, 3, 3, 1};
156*62f1e663SHui Xie       AssignableFromMoveOnly out[3]      = {};
157*62f1e663SHui Xie       auto result                        = std::unique_copy(in, in + 5, out);
158*62f1e663SHui Xie       AssignableFromMoveOnly expected[3] = {1, 3, 1};
159*62f1e663SHui Xie       assert(std::equal(out, out + 3, expected));
160*62f1e663SHui Xie       assert(result == out + 3);
161*62f1e663SHui Xie     }
162*62f1e663SHui Xie 
1634bfb9313SMarshall Clow #if TEST_STD_VER > 17
1644bfb9313SMarshall Clow     static_assert(test_constexpr());
1654bfb9313SMarshall Clow #endif
1662df59c50SJF Bastien 
1672df59c50SJF Bastien   return 0;
1685a83710eSEric Fiselier }
169