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 //          EquivalenceRelation<auto, InIter::value_type> Pred>
135a83710eSEric Fiselier //   requires OutputIterator<OutIter, RvalueOf<InIter::value_type>::type>
145a83710eSEric Fiselier //         && HasAssign<InIter::value_type, InIter::reference>
155a83710eSEric Fiselier //         && Constructible<InIter::value_type, InIter::reference>
165a83710eSEric Fiselier //         && CopyConstructible<Pred>
174bfb9313SMarshall Clow //   constexpr OutIter        // constexpr after C++17
185a83710eSEric Fiselier //   unique_copy(InIter first, InIter last, OutIter result, Pred pred);
195a83710eSEric Fiselier 
205a83710eSEric Fiselier #include <algorithm>
215a83710eSEric Fiselier #include <cassert>
225a83710eSEric Fiselier 
234bfb9313SMarshall Clow #include "test_macros.h"
245a83710eSEric Fiselier #include "test_iterators.h"
255a83710eSEric Fiselier 
264bfb9313SMarshall Clow #if TEST_STD_VER > 17
test_constexpr()274bfb9313SMarshall Clow TEST_CONSTEXPR bool test_constexpr() {
284bfb9313SMarshall Clow           int ia[]       = {0, 1, 2, 2, 4};
294bfb9313SMarshall Clow           int ib[]       = {0, 0, 0, 0, 0};
304bfb9313SMarshall Clow     const int expected[] = {0, 1, 2, 4};
314bfb9313SMarshall Clow 
324bfb9313SMarshall Clow     auto it = std::unique_copy(std::begin(ia), std::end(ia), std::begin(ib),
334bfb9313SMarshall Clow                          [](int a, int b) {return a == b; });
344bfb9313SMarshall Clow     return it == (std::begin(ib) + std::size(expected))
354bfb9313SMarshall Clow         && *it == 0 // don't overwrite final value in output
364bfb9313SMarshall Clow         && std::equal(std::begin(ib), it, std::begin(expected), std::end(expected))
374bfb9313SMarshall Clow         ;
384bfb9313SMarshall Clow     }
394bfb9313SMarshall Clow #endif
404bfb9313SMarshall Clow 
415a83710eSEric Fiselier struct count_equal
425a83710eSEric Fiselier {
435a83710eSEric Fiselier     static unsigned count;
445a83710eSEric Fiselier     template <class T>
operator ()count_equal455a83710eSEric Fiselier     bool operator()(const T& x, const T& y)
465a83710eSEric Fiselier         {++count; return x == y;}
475a83710eSEric Fiselier };
485a83710eSEric Fiselier 
495a83710eSEric Fiselier unsigned count_equal::count = 0;
505a83710eSEric Fiselier 
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     count_equal::count = 0;
595a83710eSEric Fiselier     OutIter r = std::unique_copy(InIter(ia), InIter(ia+sa), OutIter(ja), count_equal());
605a83710eSEric Fiselier     assert(base(r) == ja + sa);
615a83710eSEric Fiselier     assert(ja[0] == 0);
625a83710eSEric Fiselier     assert(count_equal::count == sa-1);
635a83710eSEric Fiselier 
645a83710eSEric Fiselier     const int ib[] = {0, 1};
655a83710eSEric Fiselier     const unsigned sb = sizeof(ib)/sizeof(ib[0]);
665a83710eSEric Fiselier     int jb[sb] = {-1};
675a83710eSEric Fiselier     count_equal::count = 0;
685a83710eSEric Fiselier     r = std::unique_copy(InIter(ib), InIter(ib+sb), OutIter(jb), count_equal());
695a83710eSEric Fiselier     assert(base(r) == jb + sb);
705a83710eSEric Fiselier     assert(jb[0] == 0);
715a83710eSEric Fiselier     assert(jb[1] == 1);
725a83710eSEric Fiselier     assert(count_equal::count == sb-1);
735a83710eSEric Fiselier 
745a83710eSEric Fiselier     const int ic[] = {0, 0};
755a83710eSEric Fiselier     const unsigned sc = sizeof(ic)/sizeof(ic[0]);
765a83710eSEric Fiselier     int jc[sc] = {-1};
775a83710eSEric Fiselier     count_equal::count = 0;
785a83710eSEric Fiselier     r = std::unique_copy(InIter(ic), InIter(ic+sc), OutIter(jc), count_equal());
795a83710eSEric Fiselier     assert(base(r) == jc + 1);
805a83710eSEric Fiselier     assert(jc[0] == 0);
815a83710eSEric Fiselier     assert(count_equal::count == sc-1);
825a83710eSEric Fiselier 
835a83710eSEric Fiselier     const int id[] = {0, 0, 1};
845a83710eSEric Fiselier     const unsigned sd = sizeof(id)/sizeof(id[0]);
855a83710eSEric Fiselier     int jd[sd] = {-1};
865a83710eSEric Fiselier     count_equal::count = 0;
875a83710eSEric Fiselier     r = std::unique_copy(InIter(id), InIter(id+sd), OutIter(jd), count_equal());
885a83710eSEric Fiselier     assert(base(r) == jd + 2);
895a83710eSEric Fiselier     assert(jd[0] == 0);
905a83710eSEric Fiselier     assert(jd[1] == 1);
915a83710eSEric Fiselier     assert(count_equal::count == sd-1);
925a83710eSEric Fiselier 
935a83710eSEric Fiselier     const int ie[] = {0, 0, 1, 0};
945a83710eSEric Fiselier     const unsigned se = sizeof(ie)/sizeof(ie[0]);
955a83710eSEric Fiselier     int je[se] = {-1};
965a83710eSEric Fiselier     count_equal::count = 0;
975a83710eSEric Fiselier     r = std::unique_copy(InIter(ie), InIter(ie+se), OutIter(je), count_equal());
985a83710eSEric Fiselier     assert(base(r) == je + 3);
995a83710eSEric Fiselier     assert(je[0] == 0);
1005a83710eSEric Fiselier     assert(je[1] == 1);
1015a83710eSEric Fiselier     assert(je[2] == 0);
1025a83710eSEric Fiselier     assert(count_equal::count == se-1);
1035a83710eSEric Fiselier 
1045a83710eSEric Fiselier     const int ig[] = {0, 0, 1, 1};
1055a83710eSEric Fiselier     const unsigned sg = sizeof(ig)/sizeof(ig[0]);
1065a83710eSEric Fiselier     int jg[sg] = {-1};
1075a83710eSEric Fiselier     count_equal::count = 0;
1085a83710eSEric Fiselier     r = std::unique_copy(InIter(ig), InIter(ig+sg), OutIter(jg), count_equal());
1095a83710eSEric Fiselier     assert(base(r) == jg + 2);
1105a83710eSEric Fiselier     assert(jg[0] == 0);
1115a83710eSEric Fiselier     assert(jg[1] == 1);
1125a83710eSEric Fiselier     assert(count_equal::count == sg-1);
1135a83710eSEric Fiselier 
1145a83710eSEric Fiselier     const int ih[] = {0, 1, 1};
1155a83710eSEric Fiselier     const unsigned sh = sizeof(ih)/sizeof(ih[0]);
1165a83710eSEric Fiselier     int jh[sh] = {-1};
1175a83710eSEric Fiselier     count_equal::count = 0;
1185a83710eSEric Fiselier     r = std::unique_copy(InIter(ih), InIter(ih+sh), OutIter(jh), count_equal());
1195a83710eSEric Fiselier     assert(base(r) == jh + 2);
1205a83710eSEric Fiselier     assert(jh[0] == 0);
1215a83710eSEric Fiselier     assert(jh[1] == 1);
1225a83710eSEric Fiselier     assert(count_equal::count == sh-1);
1235a83710eSEric Fiselier 
1245a83710eSEric Fiselier     const int ii[] = {0, 1, 1, 1, 2, 2, 2};
1255a83710eSEric Fiselier     const unsigned si = sizeof(ii)/sizeof(ii[0]);
1265a83710eSEric Fiselier     int ji[si] = {-1};
1275a83710eSEric Fiselier     count_equal::count = 0;
1285a83710eSEric Fiselier     r = std::unique_copy(InIter(ii), InIter(ii+si), OutIter(ji), count_equal());
1295a83710eSEric Fiselier     assert(base(r) == ji + 3);
1305a83710eSEric Fiselier     assert(ji[0] == 0);
1315a83710eSEric Fiselier     assert(ji[1] == 1);
1325a83710eSEric Fiselier     assert(ji[2] == 2);
1335a83710eSEric Fiselier     assert(count_equal::count == si-1);
1345a83710eSEric Fiselier }
1355a83710eSEric Fiselier 
main(int,char **)1362df59c50SJF Bastien int main(int, char**)
1375a83710eSEric Fiselier {
138*5e97d37bSMark de Wever     test<cpp17_input_iterator<const int*>, cpp17_output_iterator<int*> >();
139773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, forward_iterator<int*> >();
140773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, bidirectional_iterator<int*> >();
141773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, random_access_iterator<int*> >();
142773ae441SChristopher Di Bella     test<cpp17_input_iterator<const int*>, int*>();
1435a83710eSEric Fiselier 
144*5e97d37bSMark de Wever     test<forward_iterator<const int*>, cpp17_output_iterator<int*> >();
1455a83710eSEric Fiselier     test<forward_iterator<const int*>, forward_iterator<int*> >();
1465a83710eSEric Fiselier     test<forward_iterator<const int*>, bidirectional_iterator<int*> >();
1475a83710eSEric Fiselier     test<forward_iterator<const int*>, random_access_iterator<int*> >();
1485a83710eSEric Fiselier     test<forward_iterator<const int*>, int*>();
1495a83710eSEric Fiselier 
150*5e97d37bSMark de Wever     test<bidirectional_iterator<const int*>, cpp17_output_iterator<int*> >();
1515a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, forward_iterator<int*> >();
1525a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, bidirectional_iterator<int*> >();
1535a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, random_access_iterator<int*> >();
1545a83710eSEric Fiselier     test<bidirectional_iterator<const int*>, int*>();
1555a83710eSEric Fiselier 
156*5e97d37bSMark de Wever     test<random_access_iterator<const int*>, cpp17_output_iterator<int*> >();
1575a83710eSEric Fiselier     test<random_access_iterator<const int*>, forward_iterator<int*> >();
1585a83710eSEric Fiselier     test<random_access_iterator<const int*>, bidirectional_iterator<int*> >();
1595a83710eSEric Fiselier     test<random_access_iterator<const int*>, random_access_iterator<int*> >();
1605a83710eSEric Fiselier     test<random_access_iterator<const int*>, int*>();
1615a83710eSEric Fiselier 
162*5e97d37bSMark de Wever     test<const int*, cpp17_output_iterator<int*> >();
1635a83710eSEric Fiselier     test<const int*, forward_iterator<int*> >();
1645a83710eSEric Fiselier     test<const int*, bidirectional_iterator<int*> >();
1655a83710eSEric Fiselier     test<const int*, random_access_iterator<int*> >();
1665a83710eSEric Fiselier     test<const int*, int*>();
1674bfb9313SMarshall Clow 
1684bfb9313SMarshall Clow #if TEST_STD_VER > 17
1694bfb9313SMarshall Clow     static_assert(test_constexpr());
1704bfb9313SMarshall Clow #endif
1712df59c50SJF Bastien 
1722df59c50SJF Bastien   return 0;
1735a83710eSEric Fiselier }
174