// Range v3 library // // Copyright Eric Niebler 2014-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // //===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include #include #include #include #include #include #include #include "../simple_test.hpp" #include "../test_utils.hpp" #include "../test_iterators.hpp" template void test_iter() { int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}; static const int sa = sizeof(ia)/sizeof(ia[0]); int ib[] = {2, 4, 4, 6}; static const int sb = sizeof(ib)/sizeof(ib[0]); int ic[20]; int ir[] = {1, 2, 3, 3, 3, 4, 4}; static const int sr = sizeof(ir)/sizeof(ir[0]); auto set_difference = ::make_testable_2(ranges::set_difference); set_difference(Iter1(ia), Iter1(ia+sa), Iter2(ib), Iter2(ib+sb), OutIter(ic)). check([&](ranges::set_difference_result res) { CHECK((base(res.in1) - ia) == sa); CHECK((base(res.out) - ic) == sr); CHECK(std::lexicographical_compare(ic, base(res.out), ir, ir+sr) == false); ranges::fill(ic, 0); } ); int irr[] = {6}; static const int srr = sizeof(irr)/sizeof(irr[0]); set_difference(Iter1(ib), Iter1(ib+sb), Iter2(ia), Iter2(ia+sa), OutIter(ic)). check([&](ranges::set_difference_result res) { CHECK((base(res.in1) - ib) == sb); CHECK((base(res.out) - ic) == srr); CHECK(std::lexicographical_compare(ic, base(res.out), irr, irr+srr) == false); ranges::fill(ic, 0); } ); } template void test_comp() { int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}; static const int sa = sizeof(ia)/sizeof(ia[0]); int ib[] = {2, 4, 4, 6}; static const int sb = sizeof(ib)/sizeof(ib[0]); int ic[20]; int ir[] = {1, 2, 3, 3, 3, 4, 4}; static const int sr = sizeof(ir)/sizeof(ir[0]); auto set_difference = ::make_testable_2(ranges::set_difference); set_difference(Iter1(ia), Iter1(ia+sa), Iter2(ib), Iter2(ib+sb), OutIter(ic), std::less()). check([&](ranges::set_difference_result res) { CHECK((base(res.in1) - ia) == sa); CHECK((base(res.out) - ic) == sr); CHECK(std::lexicographical_compare(ic, base(res.out), ir, ir+sr) == false); ranges::fill(ic, 0); } ); int irr[] = {6}; static const int srr = sizeof(irr)/sizeof(irr[0]); set_difference(Iter1(ib), Iter1(ib+sb), Iter2(ia), Iter2(ia+sa), OutIter(ic), std::less()). check([&](ranges::set_difference_result res) { CHECK((base(res.in1) - ib) == sb); CHECK((base(res.out) - ic) == srr); CHECK(std::lexicographical_compare(ic, base(res.out), irr, irr+srr) == false); ranges::fill(ic, 0); } ); } template void test() { test_iter(); test_comp(); } struct S { int i; }; struct T { int j; }; struct U { int k; U& operator=(S s) { k = s.i; return *this;} U& operator=(T t) { k = t.j; return *this;} }; constexpr bool test_constexpr() { using namespace ranges; using IL = std::initializer_list; int ia[] = {1, 2, 2, 3, 3, 3, 4, 4, 4, 4}; const int sa = sizeof(ia) / sizeof(ia[0]); int ib[] = {2, 4, 4, 6}; const int sb = sizeof(ib) / sizeof(ib[0]); int ic[20] = {0}; int ir[] = {1, 2, 3, 3, 3, 4, 4}; const int sr = sizeof(ir) / sizeof(ir[0]); const auto res = set_difference(ia, IL{2, 4, 4, 6}, ic, less{}); STATIC_CHECK_RETURN((res.in1 - ia) == sa); STATIC_CHECK_RETURN((res.out - ic) == sr); STATIC_CHECK_RETURN(lexicographical_compare(ic, res.out, ir, ir + sr, less{}) == 0); fill(ic, 0); int irr[] = {6}; const int srr = sizeof(irr) / sizeof(irr[0]); const auto res2 = set_difference(ib, IL{1, 2, 2, 3, 3, 3, 4, 4, 4, 4}, ic, less{}); STATIC_CHECK_RETURN((res2.in1 - ib) == sb); STATIC_CHECK_RETURN((res2.out - ic) == srr); STATIC_CHECK_RETURN(lexicographical_compare(ic, res2.out, irr, irr + srr, less{}) == 0); return true; } int main() { #ifdef SET_DIFFERENCE_1 test, InputIterator, OutputIterator >(); test, InputIterator, ForwardIterator >(); test, InputIterator, BidirectionalIterator >(); test, InputIterator, RandomAccessIterator >(); test, InputIterator, int*>(); test, ForwardIterator, OutputIterator >(); test, ForwardIterator, ForwardIterator >(); test, ForwardIterator, BidirectionalIterator >(); test, ForwardIterator, RandomAccessIterator >(); test, ForwardIterator, int*>(); test, BidirectionalIterator, OutputIterator >(); test, BidirectionalIterator, ForwardIterator >(); test, BidirectionalIterator, BidirectionalIterator >(); test, BidirectionalIterator, RandomAccessIterator >(); test, BidirectionalIterator, int*>(); test, RandomAccessIterator, OutputIterator >(); test, RandomAccessIterator, ForwardIterator >(); test, RandomAccessIterator, BidirectionalIterator >(); test, RandomAccessIterator, RandomAccessIterator >(); test, RandomAccessIterator, int*>(); test, const int*, OutputIterator >(); test, const int*, ForwardIterator >(); test, const int*, BidirectionalIterator >(); test, const int*, RandomAccessIterator >(); test, const int*, int*>(); #endif #ifdef SET_DIFFERENCE_2 test, InputIterator, OutputIterator >(); test, InputIterator, ForwardIterator >(); test, InputIterator, BidirectionalIterator >(); test, InputIterator, RandomAccessIterator >(); test, InputIterator, int*>(); test, ForwardIterator, OutputIterator >(); test, ForwardIterator, ForwardIterator >(); test, ForwardIterator, BidirectionalIterator >(); test, ForwardIterator, RandomAccessIterator >(); test, ForwardIterator, int*>(); test, BidirectionalIterator, OutputIterator >(); test, BidirectionalIterator, ForwardIterator >(); test, BidirectionalIterator, BidirectionalIterator >(); test, BidirectionalIterator, RandomAccessIterator >(); test, BidirectionalIterator, int*>(); test, RandomAccessIterator, OutputIterator >(); test, RandomAccessIterator, ForwardIterator >(); test, RandomAccessIterator, BidirectionalIterator >(); test, RandomAccessIterator, RandomAccessIterator >(); test, RandomAccessIterator, int*>(); test, const int*, OutputIterator >(); test, const int*, ForwardIterator >(); test, const int*, BidirectionalIterator >(); test, const int*, RandomAccessIterator >(); test, const int*, int*>(); #endif #ifdef SET_DIFFERENCE_3 test, InputIterator, OutputIterator >(); test, InputIterator, ForwardIterator >(); test, InputIterator, BidirectionalIterator >(); test, InputIterator, RandomAccessIterator >(); test, InputIterator, int*>(); test, ForwardIterator, OutputIterator >(); test, ForwardIterator, ForwardIterator >(); test, ForwardIterator, BidirectionalIterator >(); test, ForwardIterator, RandomAccessIterator >(); test, ForwardIterator, int*>(); test, BidirectionalIterator, OutputIterator >(); test, BidirectionalIterator, ForwardIterator >(); test, BidirectionalIterator, BidirectionalIterator >(); test, BidirectionalIterator, RandomAccessIterator >(); test, BidirectionalIterator, int*>(); test, RandomAccessIterator, OutputIterator >(); test, RandomAccessIterator, ForwardIterator >(); test, RandomAccessIterator, BidirectionalIterator >(); test, RandomAccessIterator, RandomAccessIterator >(); test, RandomAccessIterator, int*>(); test, const int*, OutputIterator >(); test, const int*, ForwardIterator >(); test, const int*, BidirectionalIterator >(); test, const int*, RandomAccessIterator >(); test, const int*, int*>(); #endif #ifdef SET_DIFFERENCE_4 test, InputIterator, OutputIterator >(); test, InputIterator, ForwardIterator >(); test, InputIterator, BidirectionalIterator >(); test, InputIterator, RandomAccessIterator >(); test, InputIterator, int*>(); test, ForwardIterator, OutputIterator >(); test, ForwardIterator, ForwardIterator >(); test, ForwardIterator, BidirectionalIterator >(); test, ForwardIterator, RandomAccessIterator >(); test, ForwardIterator, int*>(); test, BidirectionalIterator, OutputIterator >(); test, BidirectionalIterator, ForwardIterator >(); test, BidirectionalIterator, BidirectionalIterator >(); test, BidirectionalIterator, RandomAccessIterator >(); test, BidirectionalIterator, int*>(); test, RandomAccessIterator, OutputIterator >(); test, RandomAccessIterator, ForwardIterator >(); test, RandomAccessIterator, BidirectionalIterator >(); test, RandomAccessIterator, RandomAccessIterator >(); test, RandomAccessIterator, int*>(); test, const int*, OutputIterator >(); test, const int*, ForwardIterator >(); test, const int*, BidirectionalIterator >(); test, const int*, RandomAccessIterator >(); test, const int*, int*>(); #endif #ifdef SET_DIFFERENCE_5 test, OutputIterator >(); test, BidirectionalIterator >(); test, BidirectionalIterator >(); test, RandomAccessIterator >(); test, int*>(); test, OutputIterator >(); test, ForwardIterator >(); test, BidirectionalIterator >(); test, RandomAccessIterator >(); test, int*>(); test, OutputIterator >(); test, ForwardIterator >(); test, BidirectionalIterator >(); test, RandomAccessIterator >(); test, int*>(); test, OutputIterator >(); test, ForwardIterator >(); test, BidirectionalIterator >(); test, RandomAccessIterator >(); test, int*>(); test >(); test >(); test >(); test >(); test(); #endif #ifdef SET_DIFFERENCE_6 // Test projections { S ia[] = {S{1}, S{2}, S{2}, S{3}, S{3}, S{3}, S{4}, S{4}, S{4}, S{4}}; static const int sa = sizeof(ia)/sizeof(ia[0]); T ib[] = {T{2}, T{4}, T{4}, T{6}}; static const int sb = sizeof(ib)/sizeof(ib[0]); U ic[20]; int ir[] = {1, 2, 3, 3, 3, 4, 4}; static const int sr = sizeof(ir)/sizeof(ir[0]); ranges::set_difference_result res = ranges::set_difference(ia, ib, ic, std::less(), &S::i, &T::j); CHECK((res.in1 - ia) == sa); CHECK((res.out - ic) == sr); CHECK(ranges::lexicographical_compare(ic, res.out, ir, ir+sr, std::less(), &U::k) == false); ranges::fill(ic, U{0}); int irr[] = {6}; static const int srr = sizeof(irr)/sizeof(irr[0]); ranges::set_difference_result res2 = ranges::set_difference(ib, ia, ic, std::less(), &T::j, &S::i); CHECK((res2.in1 - ib) == sb); CHECK((res2.out - ic) == srr); CHECK(ranges::lexicographical_compare(ic, res2.out, ir, irr+srr, std::less(), &U::k) == false); } // Test rvalue ranges { S ia[] = {S{1}, S{2}, S{2}, S{3}, S{3}, S{3}, S{4}, S{4}, S{4}, S{4}}; T ib[] = {T{2}, T{4}, T{4}, T{6}}; static const int sb = sizeof(ib)/sizeof(ib[0]); U ic[20]; int ir[] = {1, 2, 3, 3, 3, 4, 4}; static const int sr = sizeof(ir)/sizeof(ir[0]); auto res = ranges::set_difference(std::move(ia), ranges::views::all(ib), ic, std::less(), &S::i, &T::j); #ifndef RANGES_WORKAROUND_MSVC_573728 CHECK(::is_dangling(res.in1)); #endif // RANGES_WORKAROUND_MSVC_573728 CHECK((res.out - ic) == sr); CHECK(ranges::lexicographical_compare(ic, res.out, ir, ir+sr, std::less(), &U::k) == false); ranges::fill(ic, U{0}); int irr[] = {6}; static const int srr = sizeof(irr)/sizeof(irr[0]); auto res2 = ranges::set_difference(ranges::views::all(ib), ranges::views::all(ia), ic, std::less(), &T::j, &S::i); CHECK((res2.in1 - ib) == sb); CHECK((res2.out - ic) == srr); CHECK(ranges::lexicographical_compare(ic, res2.out, ir, irr+srr, std::less(), &U::k) == false); ranges::fill(ic, U{0}); std::vector vec{S{1}, S{2}, S{2}, S{3}, S{3}, S{3}, S{4}, S{4}, S{4}, S{4}}; auto res3 = ranges::set_difference(std::move(vec), ranges::views::all(ib), ic, std::less(), &S::i, &T::j); CHECK(::is_dangling(res3.in1)); CHECK((res3.out - ic) == sr); CHECK(ranges::lexicographical_compare(ic, res3.out, ir, ir+sr, std::less(), &U::k) == false); } { STATIC_CHECK(test_constexpr()); } #endif return ::test_result(); }