//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // // template S, class Proj = identity, // indirect_equivalence_relation> C = ranges::equal_to> // constexpr subrange unique(I first, S last, C comp = {}, Proj proj = {}); // Since C++20 // // template, Proj>> C = ranges::equal_to> // requires permutable> // constexpr borrowed_subrange_t // unique(R&& r, C comp = {}, Proj proj = {}); // Since C++20 #include #include #include #include #include #include "almost_satisfies_types.h" #include "counting_predicates.h" #include "counting_projection.h" #include "test_iterators.h" template concept HasUniqueIter = requires(Iter&& iter, Sent&& sent, Comp&& comp, Proj&& proj) { std::ranges::unique( std::forward(iter), std::forward(sent), std::forward(comp), std::forward(proj)); }; static_assert(HasUniqueIter); // !permutable static_assert(!HasUniqueIter); static_assert(!HasUniqueIter); // !sentinel_for static_assert(!HasUniqueIter); // !indirect_equivalence_relation> static_assert(!HasUniqueIter>); template concept HasUniqueRange = requires(Range&& range, Comp&& comp, Proj&& proj) { std::ranges::unique(std::forward(range), std::forward(comp), std::forward(proj)); }; template using R = UncheckedRange; static_assert(HasUniqueRange>); // !forward_range static_assert(!HasUniqueRange); static_assert(!HasUniqueRange); // permutable> static_assert(!HasUniqueRange>); static_assert(!HasUniqueRange>); // !indirect_equivalence_relation, Proj>> static_assert(!HasUniqueRange, ComparatorNotCopyable>); template class SentWrapper, std::size_t N1, std::size_t N2> constexpr void testUniqueImpl(std::array input, std::array expected) { using Sent = SentWrapper; // iterator overload { auto in = input; std::same_as> decltype(auto) result = std::ranges::unique(Iter{in.data()}, Sent{Iter{in.data() + in.size()}}); assert(std::ranges::equal(std::ranges::subrange{Iter{in.data()}, result.begin()}, expected)); assert(base(result.end()) == in.data() + in.size()); } // range overload { auto in = input; std::ranges::subrange r{Iter{in.data()}, Sent{Iter{in.data() + in.size()}}}; std::same_as> decltype(auto) result = std::ranges::unique(r); assert(std::ranges::equal(std::ranges::subrange{Iter{in.data()}, result.begin()}, expected)); assert(base(result.end()) == in.data() + in.size()); } } template class SentWrapper> constexpr void testImpl() { // no consecutive elements { std::array in{1, 2, 3, 2, 1}; std::array expected{1, 2, 3, 2, 1}; testUniqueImpl(in, expected); } // one group of consecutive elements { std::array in{2, 3, 3, 3, 4, 3}; std::array expected{2, 3, 4, 3}; testUniqueImpl(in, expected); } // multiple groups of consecutive elements { std::array in{2, 3, 3, 3, 4, 3, 3, 5, 5, 5}; std::array expected{2, 3, 4, 3, 5}; testUniqueImpl(in, expected); } // all the same { std::array in{1, 1, 1, 1, 1, 1}; std::array expected{1}; testUniqueImpl(in, expected); } // empty range { std::array in{}; std::array expected{}; testUniqueImpl(in, expected); } // single element range std::array in{1}; std::array expected{1}; testUniqueImpl(in, expected); } template