From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1984) id DD58F3947420; Fri, 17 Jul 2020 12:53:10 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DD58F3947420 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1594990390; bh=ACDt8a6Vow0KUz5Pb2Uy63bYM1O3zA6iNBbjLNmoux0=; h=From:To:Subject:Date:From; b=o7Ari/Gi8/4UeXvgQwxdfdse+yRb9iwkP5L0op8Np2jRxkfm4QTVpwLMj8rzZu1W8 kLR97xRIq0yzdoWCy5ng4f18EyqnLoZ8okVFgWOcdOkrw9Uck6aL/IuDyXKblzLEub 56z5et4tAURn9xNrouaniTX6fuy9HLx8yBJdqMw4= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Tamar Christina To: gcc-cvs@gcc.gnu.org, libstdc++-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/arm-perf-staging)] libstdc++: Implement C++20 constrained algorithms X-Act-Checkin: gcc X-Git-Author: Patrick Palka X-Git-Refname: refs/vendors/ARM/heads/arm-perf-staging X-Git-Oldrev: 13f5b93e6453d121abc15c718dfcc588aca976c3 X-Git-Newrev: bc4646410a38801029817e7951bf9b99a8c41461 Message-Id: <20200717125310.DD58F3947420@sourceware.org> Date: Fri, 17 Jul 2020 12:53:10 +0000 (GMT) X-BeenThere: libstdc++-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Jul 2020 12:53:11 -0000 https://gcc.gnu.org/g:bc4646410a38801029817e7951bf9b99a8c41461 commit bc4646410a38801029817e7951bf9b99a8c41461 Author: Patrick Palka Date: Fri Jan 10 17:11:07 2020 -0500 libstdc++: Implement C++20 constrained algorithms This patch implements the C++20 ranges overloads for the algorithms in [algorithms]. Most of the algorithms were reimplemented, with each of their implementations very closely following the existing implementation in bits/stl_algo.h and bits/stl_algobase.h. The reason for reimplementing most of the algorithms instead of forwarding to their STL-style overload is because forwarding cannot be conformantly and efficiently performed for algorithms that operate on non-random-access iterators. But algorithms that operate on random access iterators can safely and efficiently be forwarded to the STL-style implementation, and this patch does so for push_heap, pop_heap, make_heap, sort_heap, sort, stable_sort, nth_element, inplace_merge and stable_partition. What's missing from this patch is debug-iterator and container specializations that are present for some of the STL-style algorithms that need to be ported over to the ranges algos. I marked them missing at TODO comments. There are also some other minor outstanding TODOs. The code that could use the most thorough review is ranges::__copy_or_move, ranges::__copy_or_move_backward, ranges::__equal and ranges::__lexicographical_compare. In the tests, I tried to test the interface of each new overload, as well as the correctness of the new implementation. libstdc++-v3/ChangeLog: Implement C++20 constrained algorithms * include/Makefile.am: Add new header. * include/Makefile.in: Regenerate. * include/std/algorithm: Include . * include/bits/ranges_algo.h: New file. * testsuite/25_algorithms/adjacent_find/constrained.cc: New test. * testsuite/25_algorithms/all_of/constrained.cc: New test. * testsuite/25_algorithms/any_of/constrained.cc: New test. * testsuite/25_algorithms/binary_search/constrained.cc: New test. * testsuite/25_algorithms/copy/constrained.cc: New test. * testsuite/25_algorithms/copy_backward/constrained.cc: New test. * testsuite/25_algorithms/copy_if/constrained.cc: New test. * testsuite/25_algorithms/copy_n/constrained.cc: New test. * testsuite/25_algorithms/count/constrained.cc: New test. * testsuite/25_algorithms/count_if/constrained.cc: New test. * testsuite/25_algorithms/equal/constrained.cc: New test. * testsuite/25_algorithms/equal_range/constrained.cc: New test. * testsuite/25_algorithms/fill/constrained.cc: New test. * testsuite/25_algorithms/fill_n/constrained.cc: New test. * testsuite/25_algorithms/find/constrained.cc: New test. * testsuite/25_algorithms/find_end/constrained.cc: New test. * testsuite/25_algorithms/find_first_of/constrained.cc: New test. * testsuite/25_algorithms/find_if/constrained.cc: New test. * testsuite/25_algorithms/find_if_not/constrained.cc: New test. * testsuite/25_algorithms/for_each/constrained.cc: New test. * testsuite/25_algorithms/generate/constrained.cc: New test. * testsuite/25_algorithms/generate_n/constrained.cc: New test. * testsuite/25_algorithms/heap/constrained.cc: New test. * testsuite/25_algorithms/includes/constrained.cc: New test. * testsuite/25_algorithms/inplace_merge/constrained.cc: New test. * testsuite/25_algorithms/is_partitioned/constrained.cc: New test. * testsuite/25_algorithms/is_permutation/constrained.cc: New test. * testsuite/25_algorithms/is_sorted/constrained.cc: New test. * testsuite/25_algorithms/is_sorted_until/constrained.cc: New test. * testsuite/25_algorithms/lexicographical_compare/constrained.cc: New test. * testsuite/25_algorithms/lower_bound/constrained.cc: New test. * testsuite/25_algorithms/max/constrained.cc: New test. * testsuite/25_algorithms/max_element/constrained.cc: New test. * testsuite/25_algorithms/merge/constrained.cc: New test. * testsuite/25_algorithms/min/constrained.cc: New test. * testsuite/25_algorithms/min_element/constrained.cc: New test. * testsuite/25_algorithms/minmax/constrained.cc: New test. * testsuite/25_algorithms/minmax_element/constrained.cc: New test. * testsuite/25_algorithms/mismatch/constrained.cc: New test. * testsuite/25_algorithms/move/constrained.cc: New test. * testsuite/25_algorithms/move_backward/constrained.cc: New test. * testsuite/25_algorithms/next_permutation/constrained.cc: New test. * testsuite/25_algorithms/none_of/constrained.cc: New test. * testsuite/25_algorithms/nth_element/constrained.cc: New test. * testsuite/25_algorithms/partial_sort/constrained.cc: New test. * testsuite/25_algorithms/partial_sort_copy/constrained.cc: New test. * testsuite/25_algorithms/partition/constrained.cc: New test. * testsuite/25_algorithms/partition_copy/constrained.cc: New test. * testsuite/25_algorithms/partition_point/constrained.cc: New test. * testsuite/25_algorithms/prev_permutation/constrained.cc: New test. * testsuite/25_algorithms/remove/constrained.cc: New test. * testsuite/25_algorithms/remove_copy/constrained.cc: New test. * testsuite/25_algorithms/remove_copy_if/constrained.cc: New test. * testsuite/25_algorithms/remove_if/constrained.cc: New test. * testsuite/25_algorithms/replace/constrained.cc: New test. * testsuite/25_algorithms/replace_copy/constrained.cc: New test. * testsuite/25_algorithms/replace_copy_if/constrained.cc: New test. * testsuite/25_algorithms/replace_if/constrained.cc: New test. * testsuite/25_algorithms/reverse/constrained.cc: New test. * testsuite/25_algorithms/reverse_copy/constrained.cc: New test. * testsuite/25_algorithms/rotate/constrained.cc: New test. * testsuite/25_algorithms/rotate_copy/constrained.cc: New test. * testsuite/25_algorithms/search/constrained.cc: New test. * testsuite/25_algorithms/search_n/constrained.cc: New test. * testsuite/25_algorithms/set_difference/constrained.cc: New test. * testsuite/25_algorithms/set_intersection/constrained.cc: New test. * testsuite/25_algorithms/set_symmetric_difference/constrained.cc: New test. * testsuite/25_algorithms/set_union/constrained.cc: New test. * testsuite/25_algorithms/shuffle/constrained.cc: New test. * testsuite/25_algorithms/sort/constrained.cc: New test. * testsuite/25_algorithms/stable_partition/constrained.cc: New test. * testsuite/25_algorithms/stable_sort/constrained.cc: New test. * testsuite/25_algorithms/swap_ranges/constrained.cc: New test. * testsuite/25_algorithms/transform/constrained.cc: New test. * testsuite/25_algorithms/unique/constrained.cc: New test. * testsuite/25_algorithms/unique_copy/constrained.cc: New test. * testsuite/25_algorithms/upper_bound/constrained.cc: New test. Diff: --- libstdc++-v3/ChangeLog | 88 + libstdc++-v3/include/Makefile.am | 1 + libstdc++-v3/include/Makefile.in | 1 + libstdc++-v3/include/bits/ranges_algo.h | 3640 ++++++++++++++++++++ libstdc++-v3/include/std/algorithm | 3 + .../25_algorithms/adjacent_find/constrained.cc | 68 + .../testsuite/25_algorithms/all_of/constrained.cc | 90 + .../testsuite/25_algorithms/any_of/constrained.cc | 88 + .../25_algorithms/binary_search/constrained.cc | 61 + .../testsuite/25_algorithms/copy/constrained.cc | 225 ++ .../25_algorithms/copy_backward/constrained.cc | 193 ++ .../testsuite/25_algorithms/copy_if/constrained.cc | 77 + .../testsuite/25_algorithms/copy_n/constrained.cc | 72 + .../testsuite/25_algorithms/count/constrained.cc | 75 + .../25_algorithms/count_if/constrained.cc | 73 + .../testsuite/25_algorithms/equal/constrained.cc | 96 + .../25_algorithms/equal_range/constrained.cc | 69 + .../testsuite/25_algorithms/fill/constrained.cc | 92 + .../testsuite/25_algorithms/fill_n/constrained.cc | 98 + .../testsuite/25_algorithms/find/constrained.cc | 75 + .../25_algorithms/find_end/constrained.cc | 98 + .../25_algorithms/find_first_of/constrained.cc | 83 + .../testsuite/25_algorithms/find_if/constrained.cc | 77 + .../25_algorithms/find_if_not/constrained.cc | 77 + .../25_algorithms/for_each/constrained.cc | 83 + .../25_algorithms/generate/constrained.cc | 77 + .../25_algorithms/generate_n/constrained.cc | 84 + .../testsuite/25_algorithms/heap/constrained.cc | 107 + .../25_algorithms/includes/constrained.cc | 74 + .../25_algorithms/inplace_merge/constrained.cc | 69 + .../25_algorithms/is_partitioned/constrained.cc | 58 + .../25_algorithms/is_permutation/constrained.cc | 85 + .../25_algorithms/is_sorted/constrained.cc | 67 + .../25_algorithms/is_sorted_until/constrained.cc | 72 + .../lexicographical_compare/constrained.cc | 164 + .../25_algorithms/lower_bound/constrained.cc | 66 + .../testsuite/25_algorithms/max/constrained.cc | 82 + .../25_algorithms/max_element/constrained.cc | 60 + .../testsuite/25_algorithms/merge/constrained.cc | 75 + .../testsuite/25_algorithms/min/constrained.cc | 82 + .../25_algorithms/min_element/constrained.cc | 60 + .../testsuite/25_algorithms/minmax/constrained.cc | 98 + .../25_algorithms/minmax_element/constrained.cc | 68 + .../25_algorithms/mismatch/constrained.cc | 76 + .../testsuite/25_algorithms/move/constrained.cc | 203 ++ .../25_algorithms/move_backward/constrained.cc | 170 + .../25_algorithms/next_permutation/constrained.cc | 83 + .../testsuite/25_algorithms/none_of/constrained.cc | 88 + .../25_algorithms/nth_element/constrained.cc | 76 + .../25_algorithms/partial_sort/constrained.cc | 84 + .../25_algorithms/partial_sort_copy/constrained.cc | 97 + .../25_algorithms/partition/constrained.cc | 71 + .../25_algorithms/partition_copy/constrained.cc | 81 + .../25_algorithms/partition_point/constrained.cc | 67 + .../25_algorithms/prev_permutation/constrained.cc | 84 + .../testsuite/25_algorithms/remove/constrained.cc | 97 + .../25_algorithms/remove_copy/constrained.cc | 109 + .../25_algorithms/remove_copy_if/constrained.cc | 113 + .../25_algorithms/remove_if/constrained.cc | 97 + .../testsuite/25_algorithms/replace/constrained.cc | 104 + .../25_algorithms/replace_copy/constrained.cc | 109 + .../25_algorithms/replace_copy_if/constrained.cc | 118 + .../25_algorithms/replace_if/constrained.cc | 109 + .../testsuite/25_algorithms/reverse/constrained.cc | 77 + .../25_algorithms/reverse_copy/constrained.cc | 74 + .../testsuite/25_algorithms/rotate/constrained.cc | 97 + .../25_algorithms/rotate_copy/constrained.cc | 93 + .../testsuite/25_algorithms/search/constrained.cc | 88 + .../25_algorithms/search_n/constrained.cc | 80 + .../25_algorithms/set_difference/constrained.cc | 87 + .../25_algorithms/set_intersection/constrained.cc | 88 + .../set_symmetric_difference/constrained.cc | 123 + .../25_algorithms/set_union/constrained.cc | 91 + .../testsuite/25_algorithms/shuffle/constrained.cc | 70 + .../testsuite/25_algorithms/sort/constrained.cc | 81 + .../25_algorithms/stable_partition/constrained.cc | 76 + .../25_algorithms/stable_sort/constrained.cc | 70 + .../25_algorithms/swap_ranges/constrained.cc | 124 + .../25_algorithms/transform/constrained.cc | 148 + .../testsuite/25_algorithms/unique/constrained.cc | 143 + .../25_algorithms/unique_copy/constrained.cc | 113 + .../25_algorithms/upper_bound/constrained.cc | 66 + 82 files changed, 10876 insertions(+) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5ce1473b621..b9c7f436a81 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,91 @@ +2020-02-07 Patrick Palka + Jonathan Wakely + + Implement C++20 constrained algorithms + * include/Makefile.am: Add new header. + * include/Makefile.in: Regenerate. + * include/std/algorithm: Include . + * include/bits/ranges_algo.h: New file. + * testsuite/25_algorithms/adjacent_find/constrained.cc: New test. + * testsuite/25_algorithms/all_of/constrained.cc: New test. + * testsuite/25_algorithms/any_of/constrained.cc: New test. + * testsuite/25_algorithms/binary_search/constrained.cc: New test. + * testsuite/25_algorithms/copy/constrained.cc: New test. + * testsuite/25_algorithms/copy_backward/constrained.cc: New test. + * testsuite/25_algorithms/copy_if/constrained.cc: New test. + * testsuite/25_algorithms/copy_n/constrained.cc: New test. + * testsuite/25_algorithms/count/constrained.cc: New test. + * testsuite/25_algorithms/count_if/constrained.cc: New test. + * testsuite/25_algorithms/equal/constrained.cc: New test. + * testsuite/25_algorithms/equal_range/constrained.cc: New test. + * testsuite/25_algorithms/fill/constrained.cc: New test. + * testsuite/25_algorithms/fill_n/constrained.cc: New test. + * testsuite/25_algorithms/find/constrained.cc: New test. + * testsuite/25_algorithms/find_end/constrained.cc: New test. + * testsuite/25_algorithms/find_first_of/constrained.cc: New test. + * testsuite/25_algorithms/find_if/constrained.cc: New test. + * testsuite/25_algorithms/find_if_not/constrained.cc: New test. + * testsuite/25_algorithms/for_each/constrained.cc: New test. + * testsuite/25_algorithms/generate/constrained.cc: New test. + * testsuite/25_algorithms/generate_n/constrained.cc: New test. + * testsuite/25_algorithms/heap/constrained.cc: New test. + * testsuite/25_algorithms/includes/constrained.cc: New test. + * testsuite/25_algorithms/inplace_merge/constrained.cc: New test. + * testsuite/25_algorithms/is_partitioned/constrained.cc: New test. + * testsuite/25_algorithms/is_permutation/constrained.cc: New test. + * testsuite/25_algorithms/is_sorted/constrained.cc: New test. + * testsuite/25_algorithms/is_sorted_until/constrained.cc: New test. + * testsuite/25_algorithms/lexicographical_compare/constrained.cc: New + test. + * testsuite/25_algorithms/lower_bound/constrained.cc: New test. + * testsuite/25_algorithms/max/constrained.cc: New test. + * testsuite/25_algorithms/max_element/constrained.cc: New test. + * testsuite/25_algorithms/merge/constrained.cc: New test. + * testsuite/25_algorithms/min/constrained.cc: New test. + * testsuite/25_algorithms/min_element/constrained.cc: New test. + * testsuite/25_algorithms/minmax/constrained.cc: New test. + * testsuite/25_algorithms/minmax_element/constrained.cc: New test. + * testsuite/25_algorithms/mismatch/constrained.cc: New test. + * testsuite/25_algorithms/move/constrained.cc: New test. + * testsuite/25_algorithms/move_backward/constrained.cc: New test. + * testsuite/25_algorithms/next_permutation/constrained.cc: New test. + * testsuite/25_algorithms/none_of/constrained.cc: New test. + * testsuite/25_algorithms/nth_element/constrained.cc: New test. + * testsuite/25_algorithms/partial_sort/constrained.cc: New test. + * testsuite/25_algorithms/partial_sort_copy/constrained.cc: New test. + * testsuite/25_algorithms/partition/constrained.cc: New test. + * testsuite/25_algorithms/partition_copy/constrained.cc: New test. + * testsuite/25_algorithms/partition_point/constrained.cc: New test. + * testsuite/25_algorithms/prev_permutation/constrained.cc: New test. + * testsuite/25_algorithms/remove/constrained.cc: New test. + * testsuite/25_algorithms/remove_copy/constrained.cc: New test. + * testsuite/25_algorithms/remove_copy_if/constrained.cc: New test. + * testsuite/25_algorithms/remove_if/constrained.cc: New test. + * testsuite/25_algorithms/replace/constrained.cc: New test. + * testsuite/25_algorithms/replace_copy/constrained.cc: New test. + * testsuite/25_algorithms/replace_copy_if/constrained.cc: New test. + * testsuite/25_algorithms/replace_if/constrained.cc: New test. + * testsuite/25_algorithms/reverse/constrained.cc: New test. + * testsuite/25_algorithms/reverse_copy/constrained.cc: New test. + * testsuite/25_algorithms/rotate/constrained.cc: New test. + * testsuite/25_algorithms/rotate_copy/constrained.cc: New test. + * testsuite/25_algorithms/search/constrained.cc: New test. + * testsuite/25_algorithms/search_n/constrained.cc: New test. + * testsuite/25_algorithms/set_difference/constrained.cc: New test. + * testsuite/25_algorithms/set_intersection/constrained.cc: New test. + * testsuite/25_algorithms/set_symmetric_difference/constrained.cc: New + test. + * testsuite/25_algorithms/set_union/constrained.cc: New test. + * testsuite/25_algorithms/shuffle/constrained.cc: New test. + * testsuite/25_algorithms/sort/constrained.cc: New test. + * testsuite/25_algorithms/stable_partition/constrained.cc: New test. + * testsuite/25_algorithms/stable_sort/constrained.cc: New test. + * testsuite/25_algorithms/swap_ranges/constrained.cc: New test. + * testsuite/25_algorithms/transform/constrained.cc: New test. + * testsuite/25_algorithms/unique/constrained.cc: New test. + * testsuite/25_algorithms/unique_copy/constrained.cc: New test. + * testsuite/25_algorithms/upper_bound/constrained.cc: New test. + 2020-02-06 Jonathan Wakely * include/bits/stl_iterator.h (__detail::__common_iter_ptr): Fix PR diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 89835759069..1d342cecbcc 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -157,6 +157,7 @@ bits_headers = \ ${bits_srcdir}/random.tcc \ ${bits_srcdir}/range_access.h \ ${bits_srcdir}/range_cmp.h \ + ${bits_srcdir}/ranges_algo.h \ ${bits_srcdir}/refwrap.h \ ${bits_srcdir}/regex.h \ ${bits_srcdir}/regex.tcc \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 123d24bb1c6..c735d67a5d3 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -502,6 +502,7 @@ bits_headers = \ ${bits_srcdir}/random.tcc \ ${bits_srcdir}/range_access.h \ ${bits_srcdir}/range_cmp.h \ + ${bits_srcdir}/ranges_algo.h \ ${bits_srcdir}/refwrap.h \ ${bits_srcdir}/regex.h \ ${bits_srcdir}/regex.tcc \ diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h new file mode 100644 index 00000000000..a9b87283f87 --- /dev/null +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -0,0 +1,3640 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGO_H +#define _RANGES_ALGO_H 1 + +#if __cplusplus > 201703L + +#include +#include +#include +// #include +#include +#include +#include // __is_byte +#include // concept uniform_random_bit_generator + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr inline bool __is_normal_iterator = false; + + template + constexpr inline bool + __is_normal_iterator<__gnu_cxx::__normal_iterator<_Iterator, + _Container>> = true; + + template + constexpr inline bool __is_reverse_iterator = false; + + template + constexpr inline bool + __is_reverse_iterator> = true; + + template + constexpr inline bool __is_move_iterator = false; + + template + constexpr inline bool + __is_move_iterator> = true; + + template + constexpr auto + __make_comp_proj(_Comp& __comp, _Proj& __proj) + { + return [&] (auto&& __lhs, auto&& __rhs) -> bool { + using _TL = decltype(__lhs); + using _TR = decltype(__rhs); + return std::__invoke(__comp, + std::__invoke(__proj, std::forward<_TL>(__lhs)), + std::__invoke(__proj, std::forward<_TR>(__rhs))); + }; + } + + template + constexpr auto + __make_pred_proj(_Pred& __pred, _Proj& __proj) + { + return [&] (_Tp&& __arg) -> bool { + return std::__invoke(__pred, + std::__invoke(__proj, std::forward<_Tp>(__arg))); + }; + } + } // namespace __detail + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + all_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> _Pred> + constexpr bool + all_of(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::all_of(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + any_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return true; + return false; + } + + template, _Proj>> _Pred> + constexpr bool + any_of(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::any_of(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + none_of(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> _Pred> + constexpr bool + none_of(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::none_of(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template + struct for_each_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Fp fun; + + template + requires convertible_to + && convertible_to + operator for_each_result<_Iter2, _F2p>() const & + { return {in, fun}; } + + template + requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p> + operator for_each_result<_Iter2, _F2p>() && + { return {std::move(in), std::move(fun)}; } + }; + + template _Sent, + typename _Proj = identity, + indirectly_unary_invocable> _Fun> + constexpr for_each_result<_Iter, _Fun> + for_each(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + std::__invoke(__f, std::__invoke(__proj, *__first)); + return { std::move(__first), std::move(__f) }; + } + + template, _Proj>> + _Fun> + constexpr for_each_result, _Fun> + for_each(_Range&& __r, _Fun __f, _Proj __proj = {}) + { + return ranges::for_each(ranges::begin(__r), ranges::end(__r), + std::move(__f), std::move(__proj)); + } + + template _Sent, typename _Tp, + typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr _Iter + find(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) + { + while (__first != __last + && !(std::__invoke(__proj, *__first) == __value)) + ++__first; + return __first; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr safe_iterator_t<_Range> + find(_Range&& __r, const _Tp& __value, _Proj __proj = {}) + { + return ranges::find(ranges::begin(__r), ranges::end(__r), __value, + std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr safe_iterator_t<_Range> + find_if(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::find_if(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr safe_iterator_t<_Range> + find_if_not(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::find_if_not(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr _Iter1 + find_first_of(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + for (; __first1 != __last1; ++__first1) + for (auto __iter = __first2; __iter != __last2; ++__iter) + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__iter))) + return __first1; + return __first1; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr safe_iterator_t<_Range1> + find_first_of(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::find_first_of(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr iter_difference_t<_Iter> + count(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __value) + ++__n; + return __n; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr range_difference_t<_Range> + count(_Range&& __r, const _Tp& __value, _Proj __proj = {}) + { + return ranges::count(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr iter_difference_t<_Iter> + count_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__n; + return __n; + } + + template, _Proj>> _Pred> + constexpr range_difference_t<_Range> + count_if(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::count_if(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template + struct mismatch_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + + template + requires convertible_to + && convertible_to + operator mismatch_result<_IIter1, _IIter2>() const & + { return {in1, in2}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + operator mismatch_result<_IIter1, _IIter2>() && + { return {std::move(in1), std::move(in2)}; } + }; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr mismatch_result<_Iter1, _Iter2> + mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + ++__first1; + ++__first2; + } + return { std::move(__first1), std::move(__first2) }; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr mismatch_result, iterator_t<_Range2>> + mismatch(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::mismatch(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + search(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + if (__first1 == __last1 || __first2 == __last2) + return {__first1, __first1}; + + for (;;) + { + for (;;) + { + if (__first1 == __last1) + return {__first1, __first1}; + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + auto __cur1 = __first1; + auto __cur2 = __first2; + for (;;) + { + if (++__cur2 == __last2) + return {__first1, ++__cur1}; + if (++__cur1 == __last1) + return {__cur1, __cur1}; + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__cur1), + std::__invoke(__proj2, *__cur2))) + { + ++__first1; + break; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr safe_subrange_t<_Range1> + search(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::search(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent, typename _Tp, + typename _Pred = ranges::equal_to, typename _Proj = identity> + requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> + constexpr subrange<_Iter> + search_n(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) + { + if (__count <= 0) + return {__first, __first}; + + auto __value_comp = [&] (_Rp&& __arg) { + return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); + }; + if (__count == 1) + { + __first = ranges::find_if(std::move(__first), __last, + std::move(__value_comp), std::move(__proj)); + if (__first == __last) + return {__first, __first}; + else + { + auto __end = __first; + return {__first, ++__end}; + } + } + + if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + auto __tail_size = __last - __first; + auto __remainder = __count; + + while (__remainder <= __tail_size) + { + __first += __remainder; + __tail_size -= __remainder; + auto __backtrack = __first; + while (__value_comp(std::__invoke(__proj, *--__backtrack))) + { + if (--__remainder == 0) + return {__first - __count, __first}; + } + } + auto __i = __first + __tail_size; + return {__i, __i}; + } + else + { + __first = ranges::find_if(__first, __last, __value_comp, __proj); + while (__first != __last) + { + auto __n = __count; + auto __i = __first; + ++__i; + while (__i != __last && __n != 1 + && __value_comp(std::__invoke(__proj, *__i))) + { + ++__i; + --__n; + } + if (__n == 1) + return {__first, __i}; + if (__i == __last) + return {__i, __i}; + __first = ranges::find_if(++__i, __last, __value_comp, __proj); + } + return {__first, __first}; + } + } + + template + requires indirectly_comparable, const _Tp*, _Pred, _Proj> + constexpr safe_subrange_t<_Range> + search_n(_Range&& __r, range_difference_t<_Range> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) + { + return ranges::search_n(ranges::begin(__r), ranges::end(__r), + std::move(__count), __value, + std::move(__pred), std::move(__proj)); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + __find_end(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred, _Proj1 __proj1, _Proj2 __proj2) + { + auto __i = ranges::next(__first1, __last1); + if (__first2 == __last2) + return {__i, __i}; + + auto __result_begin = __i; + auto __result_end = __i; + for (;;) + { + auto __new_range = ranges::search(__first1, __last1, + __first2, __last2, + __pred, __proj1, __proj2); + auto __new_result_begin = ranges::begin(__new_range); + auto __new_result_end = ranges::end(__new_range); + if (__new_result_begin == __last1) + return {__result_begin, __result_end}; + else + { + __result_begin = __new_result_begin; + __result_end = __new_result_end; + __first1 = __result_begin; + ++__first1; + } + } + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + find_end(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + if constexpr (bidirectional_iterator<_Iter1> + && bidirectional_iterator<_Iter2>) + { + auto __i1 = ranges::next(__first1, __last1); + auto __i2 = ranges::next(__first2, __last2); + auto __rresult + = ranges::search(reverse_iterator<_Iter1>{__i1}, + reverse_iterator<_Iter1>{__first1}, + reverse_iterator<_Iter2>{__i2}, + reverse_iterator<_Iter2>{__first2}, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + auto __result_first = ranges::end(__rresult).base(); + auto __result_last = ranges::begin(__rresult).base(); + if (__result_last == __first1) + return {__i1, __i1}; + else + return {__result_first, __result_last}; + } + else + return ranges::__find_end(__first1, __last1, __first2, __last2, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr safe_subrange_t<_Range1> + find_end(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::find_end(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent, + typename _Proj = identity, + indirect_binary_predicate, + projected<_Iter, _Proj>> _Pred + = ranges::equal_to> + constexpr _Iter + adjacent_find(_Iter __first, _Sent __last, + _Pred __pred = {}, _Proj __proj = {}) + { + if (__first == __last) + return __first; + auto __next = __first; + for (; ++__next != __last; __first = __next) + { + if (std::__invoke(__pred, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + return __first; + } + return __next; + } + + template, _Proj>, + projected, _Proj>> _Pred = ranges::equal_to> + constexpr safe_iterator_t<_Range> + adjacent_find(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) + { + return ranges::adjacent_find(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred + = ranges::equal_to> + constexpr bool + is_permutation(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + + if constexpr (__sized_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (auto __scan = __first1; __scan != __last1; ++__scan) + { + auto __proj_scan = std::__invoke(__proj1, *__scan); + auto __comp_scan = [&] (_Tp&& __arg) { + return std::__invoke(__pred, __proj_scan, + std::forward<_Tp>(__arg)); + }; + if (__scan != ranges::find_if(__first1, __scan, + __comp_scan, __proj1)) + continue; // We've seen this one before. + + auto __matches = ranges::count_if(__first2, __last2, + __comp_scan, __proj2); + if (__matches == 0 + || ranges::count_if(__scan, __last1, + __comp_scan, __proj1) != __matches) + return false; + } + return true; + } + + template, _Proj1>, + projected, _Proj2>> _Pred = ranges::equal_to> + constexpr bool + is_permutation(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::is_permutation(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred, typename _Proj1, typename _Proj2> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + __equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred, _Proj1 __proj1, _Proj2 __proj2) + { + // TODO: implement more specializations to at least have parity with + // std::equal. + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && is_same_v<_ValueType1, _ValueType2> + && is_pointer_v<_Iter1> + && is_pointer_v<_Iter2> + && is_same_v<_Pred, ranges::equal_to> + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + else + { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return true; + } + } + else + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + equal(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::__equal(std::__niter_base(std::move(__first1)), + std::__niter_base(std::move(__last1)), + std::__niter_base(std::move(__first2)), + std::__niter_base(std::move(__last2)), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + equal(_Range1&& __r1, _Range2&& __r2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::equal(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + + template + struct copy_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + operator copy_result<_Iter2, _Out2>() const & + { return {in, out}; } + + template + requires convertible_to<_Iter, _Iter2> + && convertible_to<_Out, _Out2> + operator copy_result<_Iter2, _Out2>() && + { return {std::move(in), std::move(out)}; } + }; + + template + using move_result = copy_result<_Iter, _Out>; + + template + using move_backward_result = copy_result<_Iter1, _Iter2>; + + template + using copy_backward_result = copy_result<_Iter1, _Iter2>; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result); + + template _Sent, + weakly_incrementable _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_result<_Iter, _Out>, + copy_result<_Iter, _Out>> + __copy_or_move(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy/std::move. + constexpr bool __normal_iterator_p + = (__detail::__is_normal_iterator<_Iter> + || __detail::__is_normal_iterator<_Out>); + constexpr bool __reverse_p + = (__detail::__is_reverse_iterator<_Iter> + && __detail::__is_reverse_iterator<_Out>); + constexpr bool __move_iterator_p = __detail::__is_move_iterator<_Iter>; + if constexpr (__move_iterator_p) + { + auto [__in, __out] + = ranges::__copy_or_move(std::move(__first).base(), + std::move(__last).base(), + std::move(__result)); + return {move_iterator{std::move(__in)}, std::move(__out)}; + } + else if constexpr (__reverse_p) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(__last.base(), + __first.base(), + __result.base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__normal_iterator_p) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result)); + return {std::__niter_wrap(__first, std::move(__in)), + std::__niter_wrap(__result, std::move(__out))}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + using _ValueTypeI = iter_value_t<_Iter>; + using _ValueTypeO = iter_value_t<_Out>; + constexpr bool __use_memmove + = (is_trivially_copyable_v<_ValueTypeI> + && is_same_v<_ValueTypeI, _ValueTypeO> + && is_pointer_v<_Iter> + && is_pointer_v<_Out>); + + if constexpr (__use_memmove) + { + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + std::__memmove<_IsMove>(__result, __first, __num); + return {__first + __num, __result + __num}; + } + else + { + for (auto __n = __last - __first; __n > 0; --__n) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + } + else + { + while (__first != __last) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + } + + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_result<_Iter, _Out> + copy(_Iter __first, _Sent __last, _Out __result) + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Out> + constexpr copy_result, _Out> + copy(_Range&& __r, _Out __result) + { + return ranges::copy(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + + template _Sent, + weakly_incrementable _Out> + requires indirectly_movable<_Iter, _Out> + constexpr move_result<_Iter, _Out> + move(_Iter __first, _Sent __last, _Out __result) + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Out> + constexpr move_result, _Out> + move(_Range&& __r, _Out __result) + { + return ranges::move(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy_backward/std::move_backward. + constexpr bool __normal_iterator_p + = (__detail::__is_normal_iterator<_Iter> + || __detail::__is_normal_iterator<_Out>); + constexpr bool __reverse_p + = (__detail::__is_reverse_iterator<_Iter> + && __detail::__is_reverse_iterator<_Out>); + if constexpr (__reverse_p) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(__last.base(), + __first.base(), + __result.base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__normal_iterator_p) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove> + (std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result)); + return {std::__niter_wrap(__first, std::move(__in)), + std::__niter_wrap(__result, std::move(__out))}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + using _ValueTypeI = iter_value_t<_Iter>; + using _ValueTypeO = iter_value_t<_Out>; + constexpr bool __use_memmove + = (is_trivially_copyable_v<_ValueTypeI> + && is_same_v<_ValueTypeI, _ValueTypeO> + && is_pointer_v<_Iter> + && is_pointer_v<_Out>); + if constexpr (__use_memmove) + { + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + std::__memmove<_IsMove>(__result - __num, __first, __num); + return {__first + __num, __result - __num}; + } + else + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + for (auto __n = __last - __first; __n > 0; --__n) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + } + else + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + while (__first != __tail) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + } + + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_copyable<_Iter1, _Iter2> + constexpr copy_backward_result<_Iter1, _Iter2> + copy_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Iter> + constexpr copy_backward_result, _Iter> + copy_backward(_Range&& __r, _Iter __result) + { + return ranges::copy_backward(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_movable<_Iter1, _Iter2> + constexpr move_backward_result<_Iter1, _Iter2> + move_backward(_Iter1 __first, _Sent1 __last, _Iter2 __result) + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Iter> + constexpr move_backward_result, _Iter> + move_backward(_Range&& __r, _Iter __result) + { + return ranges::move_backward(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + + template + using copy_n_result = copy_result<_Iter, _Out>; + + template + requires indirectly_copyable<_Iter, _Out> + constexpr copy_n_result<_Iter, _Out> + copy_n(_Iter __first, iter_difference_t<_Iter> __n, _Out __result) + { + if constexpr (random_access_iterator<_Iter>) + return ranges::copy(__first, __first + __n, std::move(__result)); + else + { + for (; __n > 0; --__n, (void)++__result, (void)++__first) + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + } + + template + using copy_if_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_if_result<_Iter, _Out> + copy_if(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> _Pred> + requires indirectly_copyable, _Out> + constexpr copy_if_result, _Out> + copy_if(_Range&& __r, _Out __result, _Pred __pred, _Proj __proj = {}) + { + return ranges::copy_if(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + + template + using swap_ranges_result = mismatch_result<_Iter1, _Iter2>; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> + requires indirectly_swappable<_Iter1, _Iter2> + constexpr swap_ranges_result<_Iter1, _Iter2> + swap_ranges(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2) + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + ranges::iter_swap(__first1, __first2); + return {std::move(__first1), std::move(__first2)}; + } + + template + requires indirectly_swappable, iterator_t<_Range2>> + constexpr swap_ranges_result, + safe_iterator_t<_Range2>> + swap_ranges(_Range1&& __r1, _Range2&& __r2) + { + return ranges::swap_ranges(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2)); + } + + template + using unary_transform_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out, + copy_constructible _Fp, typename _Proj = identity> + requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter, _Proj>>> + constexpr unary_transform_result<_Iter, _Out> + transform(_Iter __first1, _Sent __last1, _Out __result, + _Fp __op, _Proj __proj = {}) + { + for (; __first1 != __last1; ++__first1, (void)++__result) + *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); + return {std::move(__first1), std::move(__result)}; + } + + template + requires writable<_Out, + indirect_result_t<_Fp&, projected, + _Proj>>> + constexpr unary_transform_result, _Out> + transform(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) + { + return ranges::transform(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__op), std::move(__proj)); + } + + template + struct binary_transform_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + [[no_unique_address]] _Out out; + + template + requires convertible_to && + && convertible_to + && convertible_to + operator binary_transform_result<_IIter1, _IIter2, _OOut>() const & + { return {in1, in2, out}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + && convertible_to<_Out, _OOut> + operator binary_transform_result<_IIter1, _IIter2, _OOut>() && + { return {std::move(in1), std::move(in2), std::move(out)}; } + }; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, copy_constructible _Fp, + typename _Proj1 = identity, typename _Proj2 = identity> + requires writable<_Out, indirect_result_t<_Fp&, projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>>> + constexpr binary_transform_result<_Iter1, _Iter2, _Out> + transform(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2, ++__result) + *__result = std::__invoke(__binary_op, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2)); + return {std::move(__first1), std::move(__first2), std::move(__result)}; + } + + template + requires writable<_Out, indirect_result_t<_Fp&, + projected, + _Proj1>, + projected, + _Proj2>>> + constexpr binary_transform_result, + safe_iterator_t<_Range2>, _Out> + transform(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Fp __binary_op, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::transform(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__binary_op), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent, + typename _Tp1, typename _Tp2, typename _Proj = identity> + requires writable<_Iter, const _Tp2&> && + indirect_binary_predicate, const _Tp1*> + constexpr _Iter + replace(_Iter __first, _Sent __last, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __old_value) + *__first = __new_value; + return __first; + } + + template + requires writable, const _Tp2&> && + indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr safe_iterator_t<_Range> + replace(_Range&& __r, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) + { + return ranges::replace(ranges::begin(__r), ranges::end(__r), + __old_value, __new_value, std::move(__proj)); + } + + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires writable<_Iter, const _Tp&> + constexpr _Iter + replace_if(_Iter __first, _Sent __last, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__first = __new_value; + return std::move(__first); + } + + template, _Proj>> _Pred> + requires writable, const _Tp&> + constexpr safe_iterator_t<_Range> + replace_if(_Range&& __r, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) + { + return ranges::replace_if(ranges::begin(__r), ranges::end(__r), + std::move(__pred), __new_value, + std::move(__proj)); + } + + template + using replace_copy_result = copy_result<_Iter, _Out>; + + template _Sent, + typename _Tp1, typename _Tp2, output_iterator _Out, + typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, const _Tp1*> + constexpr replace_copy_result<_Iter, _Out> + replace_copy(_Iter __first, _Sent __last, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__proj, *__first) == __old_value) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, typename _Proj = identity> + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr replace_copy_result, _Out> + replace_copy(_Range&& __r, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) + { + return ranges::replace_copy(ranges::begin(__r), ranges::end(__r), + std::move(__result), __old_value, + __new_value, std::move(__proj)); + } + + template + using replace_copy_if_result = copy_result<_Iter, _Out>; + + template _Sent, + typename _Tp, output_iterator _Out, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr replace_copy_if_result<_Iter, _Out> + replace_copy_if(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, + typename _Proj = identity, + indirect_unary_predicate, _Proj>> _Pred> + requires indirectly_copyable, _Out> + constexpr replace_copy_if_result, _Out> + replace_copy_if(_Range&& __r, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) + { + return ranges::replace_copy_if(ranges::begin(__r), ranges::end(__r), + std::move(__result), std::move(__pred), + __new_value, std::move(__proj)); + } + + template _Out> + constexpr _Out + fill_n(_Out __first, iter_difference_t<_Out> __n, const _Tp& __value) + { + // TODO: implement more specializations to be at least on par with + // std::fill_n + if (__n <= 0) + return __first; + + // TODO: is __is_byte the best condition? + if constexpr (is_pointer_v<_Out> && __is_byte<_Tp>::__value) + { + __builtin_memset(__first, static_cast(__value), __n); + return __first + __n; + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __n > 0; --__n, (void)++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __n > 0; --__n, (void)++__first) + *__first = __value; + return __first; + } + } + + template _Out, sentinel_for<_Out> _Sent> + constexpr _Out + fill(_Out __first, _Sent __last, const _Tp& __value) + { + // TODO: implement more specializations to be at least on par with + // std::fill + if constexpr (sized_sentinel_for<_Sent, _Out>) + { + const auto __len = __last - __first; + return ranges::fill_n(__first, __len, __value); + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __first != __last; ++__first) + *__first = __value; + return __first; + } + } + + template _Range> + constexpr safe_iterator_t<_Range> + fill(_Range&& __r, const _Tp& __value) + { + return ranges::fill(ranges::begin(__r), ranges::end(__r), __value); + } + + template + requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + generate_n(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) + { + for (; __n > 0; --__n, (void)++__first) + *__first = std::__invoke(__gen); + return __first; + } + + template _Sent, + copy_constructible _Fp> + requires invocable<_Fp&> && writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + generate(_Out __first, _Sent __last, _Fp __gen) + { + for (; __first != __last; ++__first) + *__first = std::__invoke(__gen); + return __first; + } + + template + requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> + constexpr safe_iterator_t<_Range> + generate(_Range&& __r, _Fp __gen) + { + return ranges::generate(ranges::begin(__r), ranges::end(__r), + std::move(__gen)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + remove_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + __first = ranges::find_if(__first, __last, __pred, __proj); + if (__first == __last) + return {__first, __first}; + + auto __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = std::move(*__first); + ++__result; + } + + return {__result, __first}; + } + + template, _Proj>> _Pred> + requires permutable> + constexpr safe_subrange_t<_Range> + remove_if(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::remove_if(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr subrange<_Iter> + remove(_Iter __first, _Sent __last, const _Tp& __value, _Proj __proj = {}) + { + auto __pred = [&] (auto&& __arg) { + return std::forward(__arg) == __value; + }; + return ranges::remove_if(__first, __last, + std::move(__pred), std::move(__proj)); + } + + template + requires permutable> && + indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr safe_subrange_t<_Range> + remove(_Range&& __r, const _Tp& __value, _Proj __proj = {}) + { + return ranges::remove(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + + template + using remove_copy_if_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr remove_copy_if_result<_Iter, _Out> + remove_copy_if(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> _Pred> + requires indirectly_copyable, _Out> + constexpr remove_copy_if_result, _Out> + remove_copy_if(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) + { + return ranges::remove_copy_if(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + + template + using remove_copy_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out, typename _Tp, typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, + const _Tp*> + constexpr remove_copy_result<_Iter, _Out> + remove_copy(_Iter __first, _Sent __last, _Out __result, + const _Tp& __value, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (!(std::__invoke(__proj, *__first) == __value)) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr remove_copy_result, _Out> + remove_copy(_Range&& __r, _Out __result, + const _Tp& __value, _Proj __proj = {}) + { + return ranges::remove_copy(ranges::begin(__r), ranges::end(__r), + std::move(__result), __value, + std::move(__proj)); + + } + + template _Sent, + typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + constexpr subrange<_Iter> + unique(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + __first = ranges::adjacent_find(__first, __last, __comp, __proj); + if (__first == __last) + return {__first, __first}; + + auto __dest = __first; + ++__first; + while (++__first != __last) + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__dest), + std::__invoke(__proj, *__first))) + *++__dest = std::move(*__first); + return {++__dest, __first}; + } + + template, _Proj>> _Comp = ranges::equal_to> + requires permutable> + constexpr safe_subrange_t<_Range> + unique(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::unique(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template + using unique_copy_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable<_Iter, _Out> + && (forward_iterator<_Iter> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable<_Iter, _Out>) + constexpr unique_copy_result<_Iter, _Out> + unique_copy(_Iter __first, _Sent __last, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return {std::move(__first), std::move(__result)}; + + // TODO: perform a closer comparison with reference implementations + if constexpr (forward_iterator<_Iter>) + { + auto __next = __first; + *__result = *__next; + while (++__next != __last) + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + { + __first = __next; + *++__result = *__first; + } + return {__next, std::move(++__result)}; + } + else if constexpr (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + { + *__result = *__first; + while (++__first != __last) + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__result), + std::__invoke(__proj, *__first))) + *++__result = *__first; + return {std::move(__first), std::move(++__result)}; + } + else // indirectly_copyable_storable<_Iter, _Out> + { + auto __value = *__first; + *__result = __value; + while (++__first != __last) + { + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, __value))) + { + __value = *__first; + *++__result = __value; + } + } + return {std::move(__first), std::move(++__result)}; + } + } + + template, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable, _Out> + && (forward_iterator> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable, _Out>) + constexpr unique_copy_result, _Out> + unique_copy(_Range&& __r, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::unique_copy(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__comp), std::move(__proj)); + } + + template _Sent> + requires permutable<_Iter> + constexpr _Iter + reverse(_Iter __first, _Sent __last) + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + + if constexpr (random_access_iterator<_Iter>) + { + if (__first != __last) + { + --__tail; + while (__first < __tail) + { + ranges::iter_swap(__first, __tail); + ++__first; + --__tail; + } + } + return __i; + } + else + { + for (;;) + if (__first == __tail || __first == --__tail) + break; + else + { + ranges::iter_swap(__first, __tail); + ++__first; + } + return __i; + } + } + + template + requires permutable> + constexpr safe_iterator_t<_Range> + reverse(_Range&& __r) + { + return ranges::reverse(ranges::begin(__r), ranges::end(__r)); + } + + template + using reverse_copy_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr reverse_copy_result<_Iter, _Out> + reverse_copy(_Iter __first, _Sent __last, _Out __result) + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + while (__first != __tail) + { + --__tail; + *__result = *__tail; + ++__result; + } + return {__i, __result}; + } + + template + requires indirectly_copyable, _Out> + constexpr reverse_copy_result, _Out> + reverse_copy(_Range&& __r, _Out __result) + { + return ranges::reverse_copy(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + + template _Sent> + constexpr subrange<_Iter> + rotate(_Iter __first, _Iter __middle, _Sent __last) + { + auto __lasti = ranges::next(__first, __last); + if (__first == __middle) + return {__lasti, __lasti}; + if (__last == __middle) + return {std::move(__first), std::move(__lasti)}; + + if constexpr (random_access_iterator<_Iter>) + { + auto __n = __lasti - __first; + auto __k = __middle - __first; + + if (__k == __n - __k) + { + ranges::swap_ranges(__first, __middle, __middle, __middle + __k); + return {std::move(__middle), std::move(__lasti)}; + } + + auto __p = __first; + auto __ret = __first + (__lasti - __middle); + + for (;;) + { + if (__k < __n - __k) + { + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*__p); + ranges::move(__p + 1, __p + __n, __p); + *(__p + __n - 1) = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + ranges::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + ranges::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*(__p + __n - 1)); + ranges::move_backward(__p, __p + __n - 1, __p + __n); + *__p = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __n; + __p = __q - __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + ranges::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + std::swap(__n, __k); + } + } + } + else if constexpr (bidirectional_iterator<_Iter>) + { + auto __tail = __lasti; + + ranges::reverse(__first, __middle); + ranges::reverse(__middle, __tail); + + while (__first != __middle && __middle != __tail) + { + ranges::iter_swap(__first, --__tail); + ++__first; + } + + if (__first == __middle) + { + ranges::reverse(__middle, __tail); + return {std::move(__tail), std::move(__lasti)}; + } + else + { + ranges::reverse(__first, __middle); + return {std::move(__first), std::move(__lasti)}; + } + } + else + { + auto __first2 = __middle; + do + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } while (__first2 != __last); + + auto __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return {std::move(__ret), std::move(__lasti)}; + } + } + + template + requires permutable> + constexpr safe_subrange_t<_Range> + rotate(_Range&& __r, iterator_t<_Range> __middle) + { + return ranges::rotate(ranges::begin(__r), + std::move(__middle), + ranges::end(__r)); + } + + template + using rotate_copy_result = copy_result<_Iter, _Out>; + + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr rotate_copy_result<_Iter, _Out> + rotate_copy(_Iter __first, _Iter __middle, _Sent __last, _Out __result) + { + auto __copy1 = ranges::copy(__middle, + std::move(__last), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first), + std::move(__middle), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.out) }; + } + + template + requires indirectly_copyable, _Out> + constexpr rotate_copy_result, _Out> + rotate_copy(_Range&& __r, iterator_t<_Range> __middle, _Out __result) + { + return ranges::rotate_copy(ranges::begin(__r), + std::move(__middle), + ranges::end(__r), + std::move(__result)); + } + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + template _Sent, + typename _Gen> + requires permutable<_Iter> + && uniform_random_bit_generator> + _Iter + shuffle(_Iter __first, _Sent __last, _Gen&& __g) + { + auto __lasti = ranges::next(__first, __last); + std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); + return __lasti; + } + + template + requires permutable> + && uniform_random_bit_generator> + safe_iterator_t<_Range> + shuffle(_Range&& __r, _Gen&& __g) + { + return ranges::shuffle(ranges::begin(__r), ranges::end(__r), + std::forward<_Gen>(__g)); + } +#endif + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + push_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::push_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + push_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::push_heap(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + pop_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::pop_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + pop_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::pop_heap(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + make_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::make_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + make_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::make_heap(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + sort_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::sort_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + sort_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::sort_heap(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + is_heap_until(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + iter_difference_t<_Iter> __n = ranges::distance(__first, __last); + iter_difference_t<_Iter> __parent = 0, __child = 1; + for (; __child < __n; ++__child) + if (std::__invoke(__comp, + std::__invoke(__proj, *(__first + __parent)), + std::__invoke(__proj, *(__first + __child)))) + return __first + __child; + else if ((__child & 1) == 0) + ++__parent; + + return __first + __n; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + is_heap_until(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::is_heap_until(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + is_heap(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + return (__last + == ranges::is_heap_until(__first, __last, + std::move(__comp), + std::move(__proj))); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + is_heap(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::is_heap(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + sort(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + sort(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::sort(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + stable_sort(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::stable_sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + safe_iterator_t<_Range> + stable_sort(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::stable_sort(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + partial_sort(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __middle) + return ranges::next(__first, __last); + + ranges::make_heap(__first, __middle, __comp, __proj); + auto __i = __middle; + for (; __i != __last; ++__i) + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + { + ranges::pop_heap(__first, __middle, __comp, __proj); + ranges::iter_swap(__middle-1, __i); + ranges::push_heap(__first, __middle, __comp, __proj); + } + ranges::sort_heap(__first, __middle, __comp, __proj); + + return __i; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + partial_sort(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::partial_sort(ranges::begin(__r), + std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template + using partial_sort_copy_result = copy_result<_Iter, _Out>; + + template _Sent1, + random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> + && sortable<_Iter2, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>> + constexpr partial_sort_copy_result<_Iter1, _Iter2> + partial_sort_copy(_Iter1 __first, _Sent1 __last, + _Iter2 __result_first, _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + if (__result_first == __result_last) + { + // TODO: Eliminating the variable __lasti triggers an ICE. + auto __lasti = ranges::next(std::move(__first), + std::move(__last)); + return {std::move(__lasti), std::move(__result_first)}; + } + + auto __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); + for (; __first != __last; ++__first) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first), + std::__invoke(__proj2, *__result_first))) + { + ranges::pop_heap(__result_first, __result_real_last, + __comp, __proj2); + *(__result_real_last-1) = *__first; + ranges::push_heap(__result_first, __result_real_last, + __comp, __proj2); + } + ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); + + return {std::move(__first), std::move(__result_real_last)}; + } + + template + requires indirectly_copyable, iterator_t<_Range2>> + && sortable, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected, _Proj1>, + projected, _Proj2>> + constexpr partial_sort_copy_result, + safe_iterator_t<_Range2>> + partial_sort_copy(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::partial_sort_copy(ranges::begin(__r), ranges::end(__r), + ranges::begin(__out), ranges::end(__out), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + is_sorted_until(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return __first; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return __next; + return __next; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + is_sorted_until(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::is_sorted_until(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + is_sorted(_Iter __first, _Sent __last, _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return true; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + is_sorted(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::is_sorted(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + nth_element(_Iter __first, _Iter __nth, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::nth_element(std::move(__first), std::move(__nth), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr safe_iterator_t<_Range> + nth_element(_Range&& __r, iterator_t<_Range> __nth, + _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::nth_element(ranges::begin(__r), std::move(__nth), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + lower_bound(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + lower_bound(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::lower_bound(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + upper_bound(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + upper_bound(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::upper_bound(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr subrange<_Iter> + equal_range(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, + std::__invoke(__proj, *__middle), + __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (std::__invoke(__comp, + __value, + std::__invoke(__proj, *__middle))) + __len = __half; + else + { + auto __left + = ranges::lower_bound(__first, __middle, + __value, __comp, __proj); + ranges::advance(__first, __len); + auto __right + = ranges::upper_bound(++__middle, __first, + __value, __comp, __proj); + return {__left, __right}; + } + } + return {__first, __first}; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_subrange_t<_Range> + equal_range(_Range&& __r, const _Tp& __value, + _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::equal_range(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + binary_search(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) + { + auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); + if (__i == __last) + return false; + return !(bool)std::__invoke(__comp, __value, std::__invoke(__proj, *__i)); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + binary_search(_Range&& __r, const _Tp& __value, _Comp __comp = {}, + _Proj __proj = {}) + { + return ranges::binary_search(ranges::begin(__r), ranges::end(__r), + __value, + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + is_partitioned(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + __first = ranges::find_if_not(std::move(__first), __last, __pred, __proj); + if (__first == __last) + return true; + ++__first; + return ranges::none_of(std::move(__first), std::move(__last), + std::move(__pred), std::move(__proj)); + } + + template, _Proj>> _Pred> + constexpr bool + is_partitioned(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::is_partitioned(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + partition(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + if constexpr (bidirectional_iterator<_Iter>) + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + for (;;) + { + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + else + break; + --__tail; + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (!(bool)std::__invoke(__pred, + std::__invoke(__proj, *__tail))) + --__tail; + else + break; + ranges::iter_swap(__first, __tail); + ++__first; + } + } + else + { + if (__first == __last) + return {std::move(__first), std::move(__first)}; + + while (std::__invoke(__pred, std::__invoke(__proj, *__first))) + if (++__first == __last) + return {std::move(__first), std::move(__first)}; + + auto __next = __first; + while (++__next != __last) + if (std::__invoke(__pred, std::__invoke(__proj, *__next))) + { + ranges::iter_swap(__first, __next); + ++__first; + } + + return {std::move(__first), std::move(__next)}; + } + } + + template, _Proj>> _Pred> + requires permutable> + constexpr safe_subrange_t<_Range> + partition(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::partition(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires permutable<_Iter> + subrange<_Iter> + stable_partition(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + auto __middle + = std::stable_partition(std::move(__first), __lasti, + __detail::__make_pred_proj(__pred, __proj)); + return {std::move(__middle), std::move(__lasti)}; + } + + template, _Proj>> _Pred> + requires permutable> + safe_subrange_t<_Range> + stable_partition(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::stable_partition(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template + struct partition_copy_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out1 out1; + [[no_unique_address]] _O2 out2; + + template + requires convertible_to + && convertible_to + && convertible_to + operator partition_copy_result<_IIter, _OOut1, _OOut2>() const & + { return {in, out1, out2}; } + + template + requires convertible_to<_Iter, _IIter> + && convertible_to<_Out1, _OOut1> + && convertible_to<_O2, _OOut2> + operator partition_copy_result<_IIter, _OOut1, _OOut2>() && + { return {std::move(in), std::move(out1), std::move(out2)}; } + }; + + template _Sent, + weakly_incrementable _Out1, weakly_incrementable _O2, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out1> + && indirectly_copyable<_Iter, _O2> + constexpr partition_copy_result<_Iter, _Out1, _O2> + partition_copy(_Iter __first, _Sent __last, + _Out1 __out_true, _O2 __out_false, + _Pred __pred, _Proj __proj = {}) + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return {std::move(__first), std::move(__out_true), std::move(__out_false)}; + } + + template, _Proj>> _Pred> + requires indirectly_copyable, _Out1> + && indirectly_copyable, _O2> + constexpr partition_copy_result, _Out1, _O2> + partition_copy(_Range&& __r, _Out1 out_true, _O2 out_false, + _Pred __pred, _Proj __proj = {}) + { + return ranges::partition_copy(ranges::begin(__r), ranges::end(__r), + std::move(out_true), std::move(out_false), + std::move(__pred), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + partition_point(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> _Pred> + constexpr safe_iterator_t<_Range> + partition_point(_Range&& __r, _Pred __pred, _Proj __proj = {}) + { + return ranges::partition_point(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + + template + using merge_result = binary_transform_result<_Iter1, _Iter2, _Out>; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr merge_result<_Iter1, _Iter2, _Out> + merge(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out) }; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr merge_result, + safe_iterator_t<_Range2>, + _Out> + merge(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::merge(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + template _Sent, + typename _Comp = ranges::less, + typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + inplace_merge(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + auto __lasti = ranges::next(__first, __last); + std::inplace_merge(std::move(__first), std::move(__middle), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + safe_iterator_t<_Range> + inplace_merge(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::inplace_merge(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + includes(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + else if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else + { + ++__first1; + ++__first2; + } + + return __first2 == __last2; + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + includes(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::includes(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + template + using set_union_result = binary_transform_result<_Iter1, _Iter2, _Out>; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_union_result<_Iter1, _Iter2, _Out> + set_union(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_union_result, + safe_iterator_t<_Range2>, _Out> + set_union(_Range1&& __r1, _Range2&& __r2, _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::set_union(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + template + using set_intersection_result = binary_transform_result<_Iter1, _Iter2, _Out>; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_intersection_result<_Iter1, _Iter2, _Out> + set_intersection(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + // TODO: Eliminating these variables triggers an ICE. + auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); + auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); + return {std::move(__last1i), std::move(__last2i), std::move(__result)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_intersection_result, + safe_iterator_t<_Range2>, _Out> + set_intersection(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::set_intersection(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + template + using set_difference_result = copy_result<_Iter, _Out>; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_difference_result<_Iter1, _Out> + set_difference(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_difference_result, _Out> + set_difference(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return ranges::set_difference(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + template + using set_symmetric_difference_result + = binary_transform_result<_Iter1, _Iter2, _Out>; + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> + set_symmetric_difference(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result, + safe_iterator_t<_Range2>, + _Out> + set_symmetric_difference(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return (ranges::set_symmetric_difference + (ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2))); + } + + template> + _Comp = ranges::less> + constexpr const _Tp& + min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + min(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + min(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::min(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + + template> + _Comp = ranges::less> + constexpr const _Tp& + max(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __a), + std::__invoke(__proj, __b))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + max(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __result), + std::__invoke(__proj, __tmp))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + max(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::max(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + + template + struct minmax_result + { + [[no_unique_address]] _Tp min; + [[no_unique_address]] _Tp max; + + template + requires convertible_to + operator minmax_result<_Tp2>() const & + { return {min, max}; } + + template + requires convertible_to<_Tp, _Tp2> + operator minmax_result<_Tp2>() && + { return {std::move(min), std::move(max)}; } + }; + + template> + _Comp = ranges::less> + constexpr minmax_result + minmax(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return {__b, __a}; + else + return {__a, __b}; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr minmax_result> + minmax(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + minmax_result> __result = {*__first, *__first}; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.min))) + __result.min = std::move(__tmp); + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.max))) + __result.max = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr minmax_result<_Tp> + minmax(initializer_list<_Tp> __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::minmax(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + min_element(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + min_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::min_element(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + max_element(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__i))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr safe_iterator_t<_Range> + max_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::max_element(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template + using minmax_element_result = minmax_result<_Iter>; + + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr minmax_element_result<_Iter> + minmax_element(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return {__first, __first}; + + minmax_element_result<_Iter> __result = {__first, __first}; + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.min))) + __result.min = __i; + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.max))) + __result.max = __i; + } + return __result; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr minmax_element_result> + minmax_element(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::minmax_element(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1, typename _Proj2, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> _Comp> + constexpr bool + __lexicographical_compare(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp, _Proj1 __proj1, _Proj2 __proj2) + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && is_same_v<_ValueType1, _ValueType2> + && is_pointer_v<_Iter1> + && is_pointer_v<_Iter2> + && (is_same_v<_Comp, ranges::less> + || is_same_v<_Comp, ranges::greater>) + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const auto __len = std::min(__d1, __d2)) + { + const auto __c = std::__memcmp(__first1, __first2, __len); + if constexpr (is_same_v<_Comp, ranges::less>) + { + if (__c < 0) + return true; + if (__c > 0) + return false; + } + else if constexpr (is_same_v<_Comp, ranges::greater>) + { + if (__c > 0) + return true; + if (__c < 0) + return false; + } + else + __builtin_unreachable(); + } + return (__last1 - __first1 < __last2 - __first2); + } + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void) ++__first2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return true; + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + lexicographical_compare(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return (ranges::__lexicographical_compare + (std::__niter_base(std::move(__first1)), + std::__niter_base(std::move(__last1)), + std::__niter_base(std::move(__first2)), + std::__niter_base(std::move(__last2)), + std::move(__comp), + std::move(__proj1), std::move(__proj2))); + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + lexicographical_compare(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + return (ranges::lexicographical_compare + (ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2))); + } + + template + struct next_permutation_result + { + bool found; + _Iter in; + }; + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr next_permutation_result<_Iter> + next_permutation(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return {false, std::move(__first)}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {false, std::move(__i)}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__ii))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *--__j))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {true, std::move(__lasti)}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {false, std::move(__lasti)}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr next_permutation_result> + next_permutation(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::next_permutation(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + + template + using prev_permutation_result = next_permutation_result<_Iter>; + + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr prev_permutation_result<_Iter> + prev_permutation(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) + { + if (__first == __last) + return {false, std::move(__first)}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {false, std::move(__i)}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__ii), + std::__invoke(__proj, *__i))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *--__j), + std::__invoke(__proj, *__i))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {true, std::move(__lasti)}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {false, std::move(__lasti)}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr prev_permutation_result> + prev_permutation(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) + { + return ranges::prev_permutation(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + +} // namespace ranges +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGO_H diff --git a/libstdc++-v3/include/std/algorithm b/libstdc++-v3/include/std/algorithm index e3d34024b73..4b956b89403 100644 --- a/libstdc++-v3/include/std/algorithm +++ b/libstdc++-v3/include/std/algorithm @@ -60,6 +60,9 @@ #include // UK-300. #include #include +#if __cplusplus > 201703L +# include +#endif #if __cplusplus > 201402L // Parallel STL algorithms diff --git a/libstdc++-v3/testsuite/25_algorithms/adjacent_find/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/adjacent_find/constrained.cc new file mode 100644 index 00000000000..d56ac5a19db --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/adjacent_find/constrained.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + int y[] = { 2, 7, 8, 8, 9 }; + + VERIFY( ranges::adjacent_find(x, x+6, {}, &X::i) == x+0 ); + VERIFY( ranges::adjacent_find(x+1, x+6, {}, &X::i) == x+6 ); + VERIFY( ranges::adjacent_find(y) == y+2 ); + VERIFY( ranges::adjacent_find(y, y+4) == y+2 ); + + test_container c(x); + VERIFY( ranges::adjacent_find(c, {}, &X::i) == ranges::begin(c) ); + + test_range r(y); + auto res = ranges::adjacent_find(r); + VERIFY( *res == 8 && *++res == 8 ); +} + +void +test02() +{ + static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + static constexpr X y[] = { {2}, {6}, {8}, {10}, {11} }; + static_assert(ranges::adjacent_find(x, {}, &X::i) == x+0); + static_assert(ranges::adjacent_find(y, {}, &X::i) == y+5); +} + +int +main() +{ + test01(); + test02(); +} + diff --git a/libstdc++-v3/testsuite/25_algorithms/all_of/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/all_of/constrained.cc new file mode 100644 index 00000000000..e35a1016764 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/all_of/constrained.cc @@ -0,0 +1,90 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +struct XLess +{ + int val; + bool operator()(X& x) const { return x.i < val; } +}; + +struct ILess +{ + int val; + bool operator()(int& i) const { return i < val; } +}; + +template +struct NotZero +{ + bool operator()(T& t) const { return t != 0; } +}; + +void +test01() +{ + X x[] = { {2}, {4}, {6}, {8}, {10}, {11} }; + + VERIFY( ranges::all_of(x, x+5, XLess{11}) ); + VERIFY( ranges::all_of(x, x+5, ILess{11}, &X::i) ); + VERIFY( !ranges::all_of(x, x+6, ILess{11}, &X::i) ); + VERIFY( !ranges::all_of(x, XLess{11}) ); + VERIFY( ranges::all_of(x, XLess{12}) ); + VERIFY( ranges::all_of(x, ILess{12}, &X::i) ); + VERIFY( !ranges::all_of(x, ILess{11}, &X::i) ); + + test_container c(x); + VERIFY( ranges::all_of(c, NotZero{}, &X::i) ); + + test_range r(x); + VERIFY( ranges::all_of(r, NotZero{}, &X::i) ); + + r.bounds.first = x; + VERIFY( ranges::all_of(r, NotZero{}, [](X& x) { return &x; }) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(ranges::all_of(y, [](int j) { return j%2 == 0; }, &Y::j)); + static_assert(ranges::all_of(y, [](const Y& y) { return y.j == y.i * 2; })); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/any_of/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/any_of/constrained.cc new file mode 100644 index 00000000000..b234692d2c7 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/any_of/constrained.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +struct XLess +{ + int val; + bool operator()(X& x) const { return x.i < val; } +}; + +struct ILess +{ + int val; + bool operator()(int& i) const { return i < val; } +}; + +template +struct NotZero +{ + bool operator()(T& t) const { return t != 0; } +}; + +void +test01() +{ + X x[] = { {2}, {4}, {6}, {8}, {10}, {11} }; + + VERIFY( ranges::any_of(x, x+6, XLess{3}) ); + VERIFY( ranges::any_of(x, x+6, ILess{3}, &X::i) ); + VERIFY( !ranges::any_of(x+1, x+6, XLess{3}) ); + VERIFY( !ranges::any_of(x+1, x+6, ILess{3}, &X::i) ); + VERIFY( ranges::any_of(x, XLess{5}) ); + VERIFY( ranges::any_of(x, ILess{5}, &X::i) ); + + test_container c(x); + VERIFY( ranges::any_of(c, NotZero{}, &X::i) ); + + test_range r(x); + VERIFY( ranges::any_of(r, NotZero{}, &X::i) ); + VERIFY( ranges::any_of(r, NotZero{}, [](X& x) { return &x; }) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(ranges::any_of(y, [](int i) { return i%2 == 0; }, &Y::i)); + static_assert(ranges::any_of(y, [](const Y& y) { return y.i + y.j == 3; })); + static_assert(!ranges::any_of(y, [](const Y& y) { return y.i == y.j; })); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/binary_search/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/binary_search/constrained.cc new file mode 100644 index 00000000000..42aaa8ef2f7 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/binary_search/constrained.cc @@ -0,0 +1,61 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + float x[] = {1, 2, 3, 4, 5, 5, 6, 7}; + test_container cx(x); + for (int i = 0; i < 7; i++) + { + VERIFY( ranges::binary_search(cx, i, {}, [] (int a) { return a-1; }) ); + VERIFY( !ranges::binary_search(cx.begin(), cx.end(), i+0.5) ); + } + VERIFY( !ranges::binary_search(cx, 0) ); + + ranges::reverse(x); + test_range rx(x); + VERIFY( ranges::binary_search(rx, 5, ranges::greater{}) ); +} + +constexpr bool +test02() +{ + int x[] = {1, 2, 3}; + return (ranges::binary_search(x, 3) + && !ranges::binary_search(x, x, 3)); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc new file mode 100644 index 00000000000..85f7d649608 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy/constrained.cc @@ -0,0 +1,225 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + { + int x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + int y[7] = { 0 }; + int z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + auto [in, out] = ranges::copy(x, y); + VERIFY( ranges::equal(x, y) && in == x+7 && out == y+7 ); + VERIFY( ranges::equal(x, z) ); + } + + { + int x[3] = { 1, 2, 3 }; + char y[4] = { 0 }; + int z[3] = { 1, 2, 3 }; + test_container cx(x); + test_container cy(y); + auto [in, out] = ranges::copy(cx, ranges::begin(cy)); + VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 ); + VERIFY( ranges::equal(x, z) ); + } + + { + char x[3] = { 1, 2, 3 }; + int y[4] = { 0 }; + int z[3] = { 1, 2, 3 }; + test_range rx(x); + test_range ry(y); + auto [in, out] = ranges::copy(rx, ranges::begin(ry)); + VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 ); + VERIFY( ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::copy(x, ranges::begin(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::copy(x, ranges::begin(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::copy(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.end())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::copy(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.end())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } +} + +struct X +{ + int i; + constexpr X (int a) : i(a) { } +}; + +void +test02() +{ + int x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + int z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::copy(x, y); + VERIFY( ranges::equal(x, x+5, y, y+5, {}, {}, &X::i) ); + VERIFY( in == x+5 ); + VERIFY( out == y+5 ); + VERIFY( y[5].i == 2 ); + VERIFY( ranges::equal(x, z) ); +} + +constexpr bool +test03() +{ + bool ok = true; + int x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + int z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::copy(x, y); + ok &= ranges::equal(x, x+5, y, y+5, {}, {}, &X::i); + ok &= (in == x+5); + ok &= (out == y+5); + ok &= (y[5].i == 2); + ok &= ranges::equal(x, z); + return ok; +} + +struct Y +{ + int i; + int moved = 0; + + constexpr Y(int a) : i(a) { } + + constexpr Y(const Y&) = delete; + constexpr Y& operator=(const Y&) = delete; + + constexpr Y(Y&& other) + { + *this = std::move(other); + } + + constexpr Y& + operator=(Y&& other) + { + other.moved++; + i = other.i; + return *this; + } + + friend constexpr bool + operator==(const Y& a, const Y& b) + { return a.i == b.i; } +}; + +void +test04() +{ + Y x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + Y y[7] = { 0, 0, 0, 0, 0, 0, 0 }; + Y z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + test_range rx(x); + auto [in, out] = ranges::copy(std::move_iterator{ranges::begin(rx)}, + std::move_sentinel{ranges::end(rx)}, + ranges::begin(y)); + VERIFY( ranges::equal(x, y) && std::move(in).base().ptr == x+7 && out == y+7 ); + VERIFY( ranges::equal(x, z) ); + for (const auto& v : x) + VERIFY( v.moved == 1 ); + for (const auto& v : y) + VERIFY( v.moved == 0 ); +} + +constexpr bool +test05() +{ + bool ok = true; + Y x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + Y y[7] = { 0, 0, 0, 0, 0, 0, 0 }; + Y z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + auto [in, out] = ranges::copy(std::move_iterator{ranges::begin(x)}, + std::move_sentinel{ranges::end(x)}, + ranges::begin(y)); + ok &= ranges::equal(x, y); + ok &= in.base() == x+7; + ok &= out == y+7; + ok &= ranges::equal(x, z); + for (const auto& v : x) + ok &= v.moved == 1; + for (const auto& v : y) + ok &= v.moved == 0; + return ok; +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); + test04(); + static_assert(test05()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_backward/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy_backward/constrained.cc new file mode 100644 index 00000000000..900f78aaa73 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy_backward/constrained.cc @@ -0,0 +1,193 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + { + int x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + int y[7] = { 0 }; + int z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + auto [in, out] = ranges::copy_backward(x, ranges::end(y)); + VERIFY( ranges::equal(x, y) && in == x+7 && out == y); + VERIFY( ranges::equal(x, z) ); + } + + { + int x[3] = { 1, 2, 3 }; + char y[4] = { 0 }; + int z[3] = { 1, 2, 3 }; + test_container cx(x); + test_container cy(y); + auto [in, out] = ranges::copy_backward(cx, ranges::end(cy)); + VERIFY( ranges::equal(x, x+3, y+1, y+4) && in.ptr == x+3 && out.ptr == y+1 ); + VERIFY( ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::copy_backward(x, ranges::end(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::copy_backward(x, ranges::end(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::copy_backward(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.begin())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::copy_backward(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.begin())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } +} + +constexpr bool +test02() +{ + bool ok = true; + int x[] = { {2}, {2}, {6}, {8}, {10} }; + int y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + const int z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::copy_backward(x, ranges::end(y)); + ok &= ranges::equal(x, x+5, y+1, y+6); + ok &= (in == x+5); + ok &= (out == y+1); + ok &= (y[0] == 2); + ok &= ranges::equal(x, z); + return ok; +} + +/* move_iterators are always input_iterators and therefore do not model + * bidirectional_iterator, so I think the following tests are rightly invalid. + +struct Y +{ + int i; + int moved = 0; + + constexpr Y(int a) : i(a) { } + + constexpr Y(const Y&) = delete; + constexpr Y& operator=(const Y&) = delete; + + constexpr Y(Y&& other) + { + *this = std::move(other); + } + + constexpr Y& + operator=(Y&& other) + { + other.moved++; + i = other.i; + return *this; + } + + friend constexpr bool + operator==(const Y& a, const Y& b) + { return a.i == b.i; } +}; + +void +test02() +{ + Y x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + Y y[7] = { 0, 0, 0, 0, 0, 0, 0 }; + Y z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + test_range rx(x); + auto [in, out] = ranges::copy_backward(std::move_iterator{ranges::begin(rx)}, + std::move_sentinel{ranges::end(rx)}, + ranges::end(y)); + VERIFY( ranges::equal(x, y) && std::move(in).base().ptr == x+7 && out == y ); + VERIFY( ranges::equal(x, z) ); + for (const auto& v : x) + VERIFY( v.moved == 1 ); + for (const auto& v : y) + VERIFY( v.moved == 0 ); +} + +constexpr bool +test03() +{ + bool ok = true; + Y x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + Y y[7] = { 0, 0, 0, 0, 0, 0, 0 }; + Y z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + auto [in, out] = ranges::copy_backward(std::move_iterator{ranges::begin(x)}, + std::move_sentinel{ranges::end(x)}, + ranges::end(y)); + ok &= ranges::equal(x, y); + ok &= in.base() == x+7; + ok &= out == y; + ok &= ranges::equal(x, z); + for (const auto& v : x) + ok &= v.moved == 1; + for (const auto& v : y) + ok &= v.moved == 0; + return ok; +} +*/ + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy_if/constrained.cc new file mode 100644 index 00000000000..8a92d227f16 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy_if/constrained.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1,2,3,4,5,6,7}; + + { + const int y[] = {2,4,6}; + int w[7]; + test_range rx(x); + test_range rw(w); + auto [in,out] = ranges::copy_if(rx, rw.begin(), + [] (int a) { return (a%2)==0; }); + VERIFY( in == rx.end() && out.ptr == w+3 ); + VERIFY( ranges::equal(w, w+3, y, y+3) ); + } + + { + const int y[] = {1,3,5,7}; + int w[7]; + test_range rx(x); + test_range rw(w); + auto [in,out] = ranges::copy_if(rx, rw.begin(), + [] (int a) { return (a%2)==0; }, + [] (int a) { return a+1; }); + VERIFY( in == rx.end() && out.ptr == w+4 ); + VERIFY( ranges::equal(w, w+4, y, y+4) ); + } +} + +constexpr bool +test02() +{ + int x[] = {1,2,3}; + const int y[] = {1,3}; + int w[3]; + auto [in,out] = ranges::copy_if(x, w, [] (int a) { return (a%2)==1; }); + return ranges::equal(w, out, y, y+2); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/copy_n/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/copy_n/constrained.cc new file mode 100644 index 00000000000..78a4539826a --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/copy_n/constrained.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +template typename in_wrapper, + template typename out_wrapper> +void +test01() +{ + int x[] = {1,2,3,4,5,6,7}; + for (int i = -1; i <= 7; i++) + { + test_range rx(x); + int w[7]; + test_range rw(w); + ranges::copy_n(rx.begin(), i, rw.begin()); + if (i >= 0) + VERIFY( ranges::equal(x, x+i, w, w+i) ); + } +} + +constexpr bool +test02() +{ + int x[] = {1,2,3}; + int y[2]; + auto [in,out] = ranges::copy_n(x, 2, y); + return (in == x+2 + && out == y+2 + && ranges::equal(x, x+2, y, y+2)); +} + +int +main() +{ + test01(); + test01(); + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/count/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/count/constrained.cc new file mode 100644 index 00000000000..2a9bb27de5e --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/count/constrained.cc @@ -0,0 +1,75 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11}, {2} }; + auto res = ranges::count(x, x+7, 2, &X::i); + VERIFY( res == 3 ); + res = ranges::count(x, x+7, 8, &X::i); + VERIFY( res == 1 ); + res = ranges::count(x, x+7, 9, &X::i); + VERIFY( res == 0 ); + + test_container c(x); + res = ranges::count(c, 6, &X::i); + VERIFY( res == 1 ); + res = ranges::count(c, 9, &X::i); + VERIFY( res == 0 ); + + test_range r(x); + res = ranges::count(r, 2, &X::i); + VERIFY( res == 3 ); + + r.bounds.first = x; + res = ranges::count(r, 9, &X::i); + VERIFY( res == 0 ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6}, {1,6} }; + static_assert(ranges::count(y, 6, &Y::j) == 2); + static_assert(ranges::count(y, 5, &Y::j) == 0); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/count_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/count_if/constrained.cc new file mode 100644 index 00000000000..79cdae31826 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/count_if/constrained.cc @@ -0,0 +1,73 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11}, {2} }; + auto res = ranges::count_if(x, x+7, [] (int i) { return i % 2 == 0; }, &X::i); + VERIFY( res == 6 ); + res = ranges::count_if(x, x+7, [] (int i) { return i % 2 == 1; }, &X::i); + VERIFY( res == 1 ); + res = ranges::count_if(x, x+7, [] (int i) { return i < 0; }, &X::i); + VERIFY( res == 0 ); + + test_container c(x); + res = ranges::count_if(c, [] (int i) { return i == 2; }, &X::i); + VERIFY( res == 3 ); + res = ranges::count_if(c, [] (int i) { return i < 0; }, &X::i); + VERIFY( res == 0 ); + + test_range r(x); + res = ranges::count_if(c, [] (int i) { return i == 2; }, &X::i); + VERIFY( res == 3 ); + res = ranges::count_if(c, [] (int i) { return i < 0; }, &X::i); + VERIFY( res == 0 ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6}, {1,6} }; + static_assert(ranges::count_if(y, [] (int i) { return i < 5; }, &Y::j) == 2); + static_assert(ranges::count_if(y, [] (int i) { return i != 4; }, &Y::j) == 3); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/equal/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/equal/constrained.cc new file mode 100644 index 00000000000..231bd8cfeaa --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/equal/constrained.cc @@ -0,0 +1,96 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + int x[] = { {2}, {2}, {6}, {8}, {10}, {11}, {11} }; + int y[] = { {2}, {2}, {6}, {8}, {10}, {11}, {11} }; + X z[] = { {2}, {6}, {8}, {10}, {2}, {2} }; + int w[] = { {1}, {1}, {1}, {1}, {1} }; + + VERIFY( ranges::equal(w, w+4, w+1, w+5) ); + VERIFY( ranges::equal(w, w+5, w, w+5, ranges::greater{}, + [] (int a) { return a+1; }) ); + + test_container cx(x), cy(y); + test_container cz(z); + VERIFY( ranges::equal(cx, cy) ); + VERIFY( !ranges::equal(cx, cy, {}, [] (int a) { return a+1; }) ); + VERIFY( !ranges::equal(cx, cz, {}, {}, &X::i) ); + + test_range rx(x), ry(y); + test_range rz(z); + VERIFY( ranges::equal(rx, ry) ); + + rx.bounds.first = x; + ry.bounds.first = y; + VERIFY( !ranges::equal(rx, ry, {}, {}, [] (int a) { return a+1; }) ); + + rx.bounds.first = x; + rz.bounds.first = z; + VERIFY( !ranges::equal(rx, rz, {}, {}, &X::i) ); +} + +void +test02() +{ + static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + static constexpr X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + static constexpr int z[] = { {2}, {6}, {8}, {10}, {2}, {2} }; + static constexpr int w[] = { {2}, {6}, {8}, {10}, {2}, {2} }; + + static_assert(ranges::equal(z, w)); + static_assert(!ranges::equal(z, z+5, w+1, w+6)); + static_assert(!ranges::equal(z, z, {}, {}, [] (int a) { return a+1; })); + static_assert(!ranges::equal(x, y, {}, &X::i, &X::i)); +} + +void +test03() +{ + std::vector x = { {2}, {2}, {6}, {8}, {10}, {11} }; + std::vector y = { {2}, {2}, {6}, {8}, {10}, {11} }; + std::vector z = { {2}, {2}, {6}, {8}, {10}, {12} }; + VERIFY( ranges::equal(x, y) ); + VERIFY( !ranges::equal(x, z) ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/equal_range/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/equal_range/constrained.cc new file mode 100644 index 00000000000..4ddf4590c21 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/equal_range/constrained.cc @@ -0,0 +1,69 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1, 2, 3, 4, 5, 5, 6, 7}; + for (unsigned i = 0; i < 5; i++) + for (unsigned j = 6; j < 8; j++) + { + test_container cx(x); + auto range = ranges::equal_range(std::next(cx.begin(), i), + std::next(cx.begin(), j), + 4, {}, [] (int a) { return a-1; }); + VERIFY( range.begin().ptr == x+4 && range.end().ptr == x+6 ); + } + + ranges::reverse(x); + test_range rx(x); + auto range = ranges::equal_range(rx, 5, ranges::greater{}, + [] (int a) { return a+1; }); + VERIFY( range.begin().ptr == x+4 && range.end().ptr == x+5 ); +} + +constexpr bool +test02() +{ + int x[] = {1, 2, 3, 4, 5}; + auto range1 = ranges::equal_range(x, 6); + auto range2 = ranges::equal_range(x, x, 6); + auto range3 = ranges::equal_range(x, 1); + return (range1.begin() == x+5 && range1.end() == x+5 + && range2.begin() == x && range2.end() == x + && range3.begin() == x && range3.end() == x+1); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc new file mode 100644 index 00000000000..4813b8302ce --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/fill/constrained.cc @@ -0,0 +1,92 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; +}; + +void +test01() +{ + const int c[6] = { 17, 17, 17, 17, 17, 17 }; + { + X x[6]; + VERIFY( ranges::fill(x, X{17}) == x+6 ); + VERIFY( ranges::equal(x, c, {}, &X::i) ); + } + + { + char x[6]; + VERIFY( ranges::fill(x, 17) == x+6 ); + VERIFY( ranges::equal(x, c) ); + } + + { + X x[6]; + test_container cx(x); + VERIFY( ranges::fill(cx, X{17}) == cx.end() ); + VERIFY( ranges::equal(cx, c, {}, &X::i) ); + } + + { + int x[6]; + test_range rx(x); + VERIFY( ranges::fill(rx, 17) == rx.end() ); + VERIFY( ranges::equal(x, c) ); + } + + { + std::list list(6); + ranges::fill(list, 17); + VERIFY( ranges::equal(list, c) ); + } +} + +constexpr bool +test02() +{ + bool ok = true; + int x[5]; + ranges::fill(x, 17); + for (auto v : x) + ok &= v == 17; + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc new file mode 100644 index 00000000000..e9ce8e8fb0a --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/fill_n/constrained.cc @@ -0,0 +1,98 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; +}; + +void +test01() +{ + const int c[6] = { 17, 17, 17, 4, 5, 6 }; + { + X x[6] = { {1}, {2}, {3}, {4}, {5}, {6} }; + VERIFY( ranges::fill_n(x, 3, X{17}) == x+3 ); + VERIFY( ranges::equal(x, c, {}, &X::i) ); + } + + { + char x[6]; + VERIFY( ranges::fill_n(x, 3, 17) == x+3 ); + VERIFY( ranges::equal(x, x+3, c, c+3) ); + } + + { + X x[6] = { 1, 2, 3, 4, 5, 6 }; + test_container cx(x); + VERIFY( ranges::fill_n(cx.begin(), 3, X{17})->i == 4 ); + VERIFY( ranges::equal(cx, c, {}, &X::i) ); + } + + { + int x[6] = { 1, 2, 3, 4, 5, 6 };; + test_range rx(x); + ranges::fill_n(ranges::begin(rx), 3, 17); + VERIFY( ranges::equal(x, c) ); + } + + { + std::list list({1, 2, 3, 4, 5, 6}); + ranges::fill_n(list.begin(), 3, 17); + VERIFY( ranges::equal(list, c) ); + } +} + +constexpr bool +test02() +{ + bool ok = true; + int x[6] = { 1, 2, 3, 4, 5, 6 }; + const int y[6] = { 1, 2, 3, 4, 5, 6 }; + const int z[6] = { 17, 17, 17, 4, 5, 6 }; + + ranges::fill_n(x, 0, 17); + ranges::fill_n(x, -1, 17); + ok &= ranges::equal(x, y); + + ranges::fill_n(x, 3, 17); + ok &= ranges::equal(x, z); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/find/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/find/constrained.cc new file mode 100644 index 00000000000..6f6b9547e67 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/find/constrained.cc @@ -0,0 +1,75 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + auto res = ranges::find(x, x+6, 8, &X::i); + VERIFY( res == x+3 ); + res = ranges::find(x, x+6, 2, &X::i); + VERIFY( res == x+0 ); + res = ranges::find(x, x+6, 9, &X::i); + VERIFY( res == x+6 ); + + test_container c(x); + auto res2 = ranges::find(c, 8, &X::i); + VERIFY( res2 != ranges::end(c) && res2->i == 8 ); + res2 = ranges::find(c, 9, &X::i); + VERIFY( res2 == ranges::end(c) ); + + test_range r(x); + auto res3 = ranges::find(r, 8, &X::i); + VERIFY( res3 != ranges::end(r) && res3->i == 8 ); + + r.bounds.first = x; + res3 = ranges::find(r, 9, &X::i); + VERIFY( res3 == ranges::end(r) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(ranges::find(y, 4, &Y::j) == y+1); + static_assert(ranges::find(y, 5, &Y::j) == y+3); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc new file mode 100644 index 00000000000..b51e4a734fb --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/find_end/constrained.cc @@ -0,0 +1,98 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {10}, {11}, {2}, {6}, {8}, {10}, {11} }; + X y[] = { {10}, {11} }; + { + + test_container c(x); + auto res = ranges::find_end(c, y, {}, &X::i, &X::i); + VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(c) ); + res = ranges::find_end(c, c, {}, &X::i, &X::i); + VERIFY( std::get<0>(res) == ranges::begin(c) + && std::get<1>(res) == ranges::end(c) ); + } + + { + test_range r(x); + auto res = ranges::find_end(r, y, {}, &X::i, &X::i); + VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) ); + res = ranges::find_end(r, r, {}, &X::i, &X::i); + VERIFY( std::get<0>(res) == ranges::begin(r) + && std::get<1>(res) == ranges::end(r) ); + } + + { + test_range r(x); + auto res = ranges::find_end(r, y, {}, &X::i, &X::i); + VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) ); + res = ranges::find_end(r, r, {}, &X::i, &X::i); + VERIFY( std::get<0>(res) == ranges::begin(r) + && std::get<1>(res) == ranges::end(r) ); + } +} + +void +test02() +{ + static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {6}, {8}, {11} }; + static constexpr X y[] = { {6}, {8} }; + static constexpr int z[] = { 2, 8 }; + static constexpr int w[] = { 2 }; + + static_assert(std::get<0>(ranges::find_end(x, y, {}, &X::i, &X::i)) == x+5); + static_assert(std::get<1>(ranges::find_end(x, y, {}, &X::i, &X::i)) == x+7); + + static_assert(std::get<0>(ranges::find_end(x, z, {}, &X::i)) == x+8); + static_assert(std::get<1>(ranges::find_end(x, z, {}, &X::i)) == x+8); + + static_assert(std::get<0>(ranges::find_end(x, w, {}, &X::i)) == x+1); + static_assert(std::get<1>(ranges::find_end(x, w, {}, &X::i)) == x+2); + + static_assert(std::get<0>(ranges::find_end(x, x+6, w, w, {}, &X::i)) == x+6); + static_assert(std::get<1>(ranges::find_end(x, x+6, w, w, {}, &X::i)) == x+6); + + static_assert(std::get<0>(ranges::find_end(x, x, w, w+1, {}, &X::i)) == x+0); + static_assert(std::get<1>(ranges::find_end(x, x, w, w+1, {}, &X::i)) == x+0); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/find_first_of/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/find_first_of/constrained.cc new file mode 100644 index 00000000000..81a15761fa0 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/find_first_of/constrained.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + int y[] = { 2, 7, 8, 9 }; + X w[] = { {2}, {7}, {8}, {9} }; + + auto res = ranges::find_first_of(x, x+6, y+1, y+4, {}, &X::i); + VERIFY( res == x+3 ); + res = ranges::find_first_of(x, x+6, w, w+4, {}, &X::i, &X::i); + VERIFY( res == x+0 ); + res = ranges::find_first_of(x, x+6, y+3, y+4, {}, &X::i); + VERIFY( res == x+6 ); + + test_container c(x); + test_container d1(y+1, y+4); + auto res2 = ranges::find_first_of(c, d1, {}, &X::i); + VERIFY( res2 != ranges::end(c) && res2->i == 8 ); + + test_container d2(w+3, w+4); + res2 = ranges::find_first_of(c, d2, {}, &X::i, &X::i); + VERIFY( res2 == ranges::end(c) ); + + test_range r(x); + test_range s1(y+1, y+4); + auto res3 = ranges::find_first_of(r, s1, {}, &X::i); + VERIFY( res3 != ranges::end(r) && res3->i == 8 ); + + test_range s2(w+3, w+4); + r.bounds.first = x; + res3 = ranges::find_first_of(r, s2, {}, &X::i, &X::i); + VERIFY( res3 == ranges::end(r) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(ranges::find_first_of(y, y, {}, &Y::j, &Y::i) == y); + static_assert(ranges::find_first_of(y, y, {}, &Y::i, &Y::j) == y+1); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/find_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/find_if/constrained.cc new file mode 100644 index 00000000000..299bdd0fceb --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/find_if/constrained.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + auto res = ranges::find_if(x, x+6, [] (X& v) { return v.i == 8; }); + VERIFY( res == x+3 ); + res = ranges::find_if(x, x+6, [] (X& v) { return v.i % 2 == 0; }); + VERIFY( res == x+0 ); + res = ranges::find_if(x, x+6, [] (X& v) { return v.i == 9; }); + VERIFY( res == x+6 ); + + test_container c(x); + auto res2 = ranges::find_if(c, [] (int i) { return i > 7; }, &X::i); + VERIFY( res2 != ranges::end(c) && res2->i == 8 ); + res2 = ranges::find_if(c, [] (int i) { return i > 11; }, &X::i); + VERIFY( res2 == ranges::end(c) ); + + test_range r(x); + auto res3 = ranges::find_if(r, [] (int i) { return i > 10; }, &X::i); + VERIFY( res3 != ranges::end(r) && res3->i == 11 ); + + r.bounds.first = x; + res3 = ranges::find_if(r, [] (int i) { return i == 9; }, &X::i); + VERIFY( res3 == ranges::end(r) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(ranges::find_if(y, [] (int i) { return i > 3; }, &Y::j) + == y+1); + static_assert(ranges::find_if(y, [] (int i) { return i == 5; }, &Y::j) + == y+3); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/find_if_not/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/find_if_not/constrained.cc new file mode 100644 index 00000000000..838434aa7e0 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/find_if_not/constrained.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + auto res = ranges::find_if_not(x, x+6, [] (X& v) { return v.i != 8; }); + VERIFY( res == x+3 ); + res = ranges::find_if_not(x, x+6, [] (X& v) { return v.i % 2 == 1; }); + VERIFY( res == x+0 ); + res = ranges::find_if_not(x, x+6, [] (X& v) { return v.i != 9; }); + VERIFY( res == x+6 ); + + test_container c(x); + auto res2 = ranges::find_if_not(c, [] (int i) { return i <= 7; }, &X::i); + VERIFY( res2 != ranges::end(c) && res2->i == 8 ); + res2 = ranges::find_if_not(c, [] (int i) { return i <= 11; }, &X::i); + VERIFY( res2 == ranges::end(c) ); + + test_range r(x); + auto res3 = ranges::find_if_not(r, [] (int i) { return i <= 10; }, &X::i); + VERIFY( res3 != ranges::end(r) && res3->i == 11 ); + + r.bounds.first = x; + res3 = ranges::find_if_not(r, [] (int i) { return i != 9; }, &X::i); + VERIFY( res3 == ranges::end(r) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(ranges::find_if_not(y, [] (int i) { return i <= 3; }, &Y::j) + == y+1); + static_assert(ranges::find_if_not(y, [] (int i) { return i != 5; }, &Y::j) + == y+3); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc new file mode 100644 index 00000000000..142ad2e57da --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/for_each/constrained.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +static int a; + +void +f(int& i) +{ + a += i; +} + +void +test01() +{ + X x[] = { {2}, {4}, {6}, {8}, {10}, {11} }; + + auto res = ranges::for_each(x, x+6, f, &X::i); + VERIFY( res.in == x+6 ); + VERIFY( res.fun == &f ); + VERIFY( a == 41 ); + + test_container c(x); + int p = 0; + ranges::for_each(c, [&p](int i) { ++p; }, &X::i); + VERIFY( p == 6 ); + + test_range r(x); + int q = 0; + ranges::for_each(r, [&q](X&) { ++q; }); + VERIFY( q == 6 ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + auto f = [] + { + Y y[] = { {1,2}, {2,4}, {3,6} }; + int a = 0; + ranges::for_each(y, [&a](int i) { a += i; }, &Y::i); + return a; + }; + static_assert(f() == 6); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/generate/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/generate/constrained.cc new file mode 100644 index 00000000000..71bcbaa616d --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/generate/constrained.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + const int c[6] = { 1, 2, 3, 4, 5, 6 }; + + { + int x[6]; + int a = 1; + VERIFY( ranges::generate(x, [&] { return a++; }) == x+6 ); + VERIFY( ranges::equal(x, c) ); + } + + { + int x[6]; + int a = 1; + test_container cx(x); + VERIFY( ranges::generate(cx, [&] { return a++; }) == cx.end() ); + VERIFY( ranges::equal(cx, c) ); + } + + { + int x[6]; + int a = 1; + test_range rx(x); + VERIFY( ranges::generate(rx, [&] { return a++; }) == rx.end() ); + VERIFY( ranges::equal(x, c) ); + } +} + +constexpr bool +test02() +{ + const int c[6] = { 1, 2, 3, 4, 5, 6 }; + int x[6]; + int a = 1; + ranges::generate(x, [&] { return a++; }); + return ranges::equal(x, c); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/generate_n/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/generate_n/constrained.cc new file mode 100644 index 00000000000..ff894addecc --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/generate_n/constrained.cc @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + const int c[6] = { 1, 2, 3, 4, 5, 6 }; + + { + int x[6] = { 7, 8, 9, 4, 5, 6 }; + int a = 1; + VERIFY( ranges::generate_n(x, 3, [&] { return a++; }) == x+3 ); + VERIFY( ranges::equal(x, c) ); + } + + { + int x[6] = { 7, 8, 9, 4, 5, 6 }; + int a = 1; + test_container cx(x); + VERIFY( *ranges::generate_n(cx.begin(), 3, [&] { return a++; }) + == 4 ); + VERIFY( ranges::equal(cx, c) ); + } + + { + int x[6] = { 7, 8, 9, 4, 5, 6 }; + int a = 1; + test_range rx(x); + ranges::generate_n(ranges::begin(rx), 3, [&] { return a++; }); + VERIFY( ranges::equal(x, c) ); + } +} + +constexpr bool +test02() +{ + bool ok = true; + int c[6] = { 1, 2, 3, 4, 5, 6 }; + int x[6]; + int a = 1; + ranges::generate_n(x, 6, [&] { return a++; }); + ok &= ranges::equal(x, c); + ranges::generate_n(c, 0, [] { return -1; }); + ok &= ranges::equal(x, c); + ranges::generate_n(c, -2, [] { return -1; }); + ok &= ranges::equal(x, c); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc new file mode 100644 index 00000000000..eacf2906371 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/heap/constrained.cc @@ -0,0 +1,107 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +template typename> typename container> +void +test01() +{ + int x[50]; + + auto pred = std::greater{}; + auto proj = [] (int a) { return -a; }; + for (int i = 0; i < 50; i++) + { + std::iota(x, x+50, 1); + container rx(x); + + std::ranlux48_base g(i); + ranges::shuffle(rx, g); + + auto iter = ranges::make_heap(rx, pred, proj); + VERIFY( iter == rx.end() ); + VERIFY( ranges::is_heap(rx, pred, proj) ); + VERIFY( ranges::is_heap_until(rx, pred, proj) == rx.end() ); + + iter = ranges::pop_heap(rx, pred, proj); + VERIFY( iter == rx.end() ); + VERIFY( *(iter-1) == 50 ); + VERIFY( ranges::is_heap_until(rx, pred, proj) == iter-1 ); + + iter = ranges::pop_heap(rx.begin(), iter-1, pred, proj); + VERIFY( iter+1 == rx.end() ); + VERIFY( *(iter-1) == 49 ); + VERIFY( ranges::is_heap_until(rx, pred, proj) == iter-1 ); + + *(iter-1) = i; + iter = ranges::push_heap(rx.begin(), iter, pred, proj); + VERIFY( iter+1 == rx.end() ); + VERIFY( ranges::is_heap_until(rx, pred, proj) == iter ); + + *iter = 2*i; + iter = ranges::push_heap(rx.begin(), rx.end(), pred, proj); + VERIFY( iter == rx.end() ); + VERIFY( ranges::is_heap_until(rx, pred, proj) == iter ); + + *(rx.begin()+1) *= -1; + VERIFY( !ranges::is_heap(rx, pred, proj) ); + *(rx.begin()+1) *= -1; + VERIFY( ranges::is_heap(rx, pred, proj) ); + + iter = ranges::sort_heap(rx, pred, proj); + VERIFY( iter == rx.end() ); + VERIFY( ranges::is_sorted(rx, pred, proj) ); + } +} + +constexpr bool +test02() +{ + bool ok = true; + int x[] = {1,2,3,4,5}; + ranges::make_heap(x); + ranges::pop_heap(x); + x[4] = 7; + ranges::push_heap(x); + ok &= ranges::is_heap(x); + ok &= ranges::is_heap_until(x) == x+5; + ranges::sort_heap(x); + ok &= ranges::equal(x, (int[]){1,2,3,4,7}); + return ok; +} + +int +main() +{ + test01(); + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/includes/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/includes/constrained.cc new file mode 100644 index 00000000000..f959a1d60a4 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/includes/constrained.cc @@ -0,0 +1,74 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1,2,3,4,5,6,7}; + int y[] = {2,4,6}; + test_range rx(x), ry(y); + + VERIFY( ranges::includes(rx, ry) ); + + rx.bounds.first = x; + ry.bounds.first = y; + VERIFY( ranges::includes(rx, ry, + ranges::greater{}, + std::negate<>{}, + std::negate<>{}) ); + + test_container cx(x), cy(y); + VERIFY( ranges::includes(cx.begin(), cx.end(), + cy.begin(), cy.end(), + {}, + [] (int a) { return a+1; }, + [] (int a) { return a+2; }) ); + + VERIFY( ranges::includes(x, x+1, y, y) ); +} + +constexpr bool +test03() +{ + bool ok = true; + ok &= ranges::includes((int[]){1,2,3}, + (int[]){1}); + ok &= !ranges::includes((int[]){1,2,3}, + (int[]){1,2,3,4}); + return true; +} + +int +main() +{ + test01(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc new file mode 100644 index 00000000000..856056865d9 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/inplace_merge/constrained.cc @@ -0,0 +1,69 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1,2,3,4,5}; + for (int i = 0; i <= 5; i++) + for (int j = 0; j <= 5; j++) + { + std::vector v(x, x+i); + v.insert(v.end(), x, x+j); + ranges::sort(v); + + test_range rz(&v[0], &v[0]+i+j); + auto result = ranges::inplace_merge(rz, next(ranges::begin(rz), i)); + VERIFY( result == rz.end() ); + + VERIFY( ranges::is_sorted(rz) ); + } +} + +void +test02() +{ + struct X { int i, j; }; + X x[] = { {1, 1}, {3, 4}, {5, 5}, {2, 2}, {2, 3} }; + auto comp = ranges::greater{}; + auto proj = [] (X a) { return -a.i; }; + ranges::inplace_merge(x, x+3, x+5, comp, proj); + VERIFY( ranges::is_sorted(x, {}, &X::i) ); + VERIFY( ranges::is_sorted(x, {}, &X::j) ); +} + + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/is_partitioned/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/is_partitioned/constrained.cc new file mode 100644 index 00000000000..8035667b38d --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/is_partitioned/constrained.cc @@ -0,0 +1,58 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {2,4,6,1,3,5}; + test_container cx(x); + VERIFY( ranges::is_partitioned(cx, [] (int a) { return a%2==0; }) ); + + test_range rx(x); + VERIFY( ranges::is_partitioned(rx, + [] (int a) { return a%2==1; }, + [] (int a) { return a+1; }) ); +} + +constexpr bool +test02() +{ + int x[] = {1,2,3,4,5,6,1}; + return (ranges::is_partitioned(x, x+6, [] (int a) { return a<=2; }) + && !ranges::is_partitioned(x, x+7, [] (int a) { return a<=2; })); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc new file mode 100644 index 00000000000..c5393becc8d --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/is_permutation/constrained.cc @@ -0,0 +1,85 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + int x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + int y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + int z[] = { {2}, {6}, {8}, {10}, {2}, {2} }; + + VERIFY( ranges::is_permutation(x, x+6, y, y+6) ); + VERIFY( !ranges::is_permutation(x, x+6, y, y+5) ); + + test_container cx(x), cy(y), cz(z); + test_range rx(x), ry(y), rz(z); + VERIFY( ranges::is_permutation(cx, ry) ); + VERIFY( !ranges::is_permutation(rx, cz) ); + VERIFY( ranges::is_permutation(rx, cy) ); + VERIFY( !ranges::is_permutation(cx, rz) ); +} + +void +test02() +{ + static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + static constexpr X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + static constexpr int z[] = { {2}, {6}, {8}, {10}, {2}, {2} }; + static_assert(ranges::is_permutation(x, y, {}, &X::i, &X::i)); + static_assert(!ranges::is_permutation(x, z, {}, &X::i)); + static_assert(!ranges::is_permutation(z, y, {}, {}, &X::i)); +} + +void +test03() +{ + int x[] = { 1, 2, 3, 4 }; + int y[] = { 1, 2, 3, 3 }; + test_container cx(x); + do + do + { + VERIFY( ranges::is_permutation(cx, x) ); + VERIFY( !ranges::is_permutation(y, cx) ); + } while (std::next_permutation(y, y+4)); + while (std::next_permutation(std::begin(cx), std::end(cx))); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc new file mode 100644 index 00000000000..af00afe48e8 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/is_sorted/constrained.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {3,4,5,1}; + test_container cx(x); + VERIFY( ranges::is_sorted(cx.begin(), ranges::next(cx.begin(), 3)) ); + VERIFY( !ranges::is_sorted(cx) ); + VERIFY( !ranges::is_sorted(cx, ranges::greater{}) ); + VERIFY( ranges::is_sorted(cx, {}, [] (int a) { return 0; }) ); +} + +void +test02() +{ + int x[] = {1,2,3,4,5}; + test_range rx(x); + VERIFY( ranges::is_sorted(rx) ); + VERIFY( !ranges::is_sorted(ranges::begin(rx), + next(ranges::begin(rx), 2), + ranges::greater{}) ); +} + +constexpr bool +test03() +{ + int x[] = { 1,2 }; + return (ranges::is_sorted(x) + && ranges::is_sorted(x, x) ); +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc new file mode 100644 index 00000000000..a81aa49ee94 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/is_sorted_until/constrained.cc @@ -0,0 +1,72 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {3,4,5,1}; + test_container cx(x); + VERIFY( ranges::is_sorted_until(cx.begin(), + ranges::next(cx.begin(), 3)) + == ranges::next(cx.begin(), 3) ); + VERIFY( ranges::is_sorted_until(cx) == ranges::next(cx.begin(), 3) ); + VERIFY( ranges::is_sorted_until(cx, ranges::greater{}) + == ranges::next(cx.begin(), 1) ); + VERIFY( ranges::is_sorted_until(cx, {}, [] (int a) { return 0; }) + == cx.end() ); +} + +void +test02() +{ + int x[] = {1,2,3,4,5}; + test_range rx(x); + VERIFY( ranges::is_sorted_until(rx) == ranges::end(rx) ); + VERIFY( ranges::is_sorted_until(ranges::begin(rx), + next(ranges::begin(rx), 2), + ranges::greater{}) + == next(ranges::begin(rx), 1) ); +} + +constexpr bool +test03() +{ + int x[] = { 1,2 }; + return (ranges::is_sorted_until(x) == x+2 + && ranges::is_sorted_until(x, x) == x ); +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/constrained.cc new file mode 100644 index 00000000000..b82c872bbbb --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/constrained.cc @@ -0,0 +1,164 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1, 2, 3, 4, 5}; + char y[] = {1, 2, 3, 5}; + long z[] = {1, 2, 3, 4, 5, 6}; + + { + test_range rx(x); + test_range ry(y); + test_range rz(z); + + VERIFY( ranges::lexicographical_compare(rx, ry) ); + rx.bounds.first = x; + ry.bounds.first = y; + VERIFY( !ranges::lexicographical_compare(ry, rx) ); + } + + test_range rx(x); + test_range ry(y); + test_range rz(z); + + VERIFY( ranges::lexicographical_compare(rx, rz) ); + VERIFY( !ranges::lexicographical_compare(rz, rx) ); + + VERIFY( !ranges::lexicographical_compare(rx, rx) ); + VERIFY( ranges::lexicographical_compare(rx, rx, {}, std::negate<>{}) ); + VERIFY( ranges::lexicographical_compare(rx, rx, std::greater{}, + {}, std::negate<>{}) ); + + VERIFY( !ranges::lexicographical_compare(rx, ry, {}, + std::negate<>{}, + std::negate<>{}) ); + VERIFY( ranges::lexicographical_compare(ry, rx, {}, + std::negate<>{}, + std::negate<>{}) ); + + VERIFY( ranges::lexicographical_compare(rx, rz, ranges::greater{}) ); + VERIFY( !ranges::lexicographical_compare(rz, rx, ranges::greater{}) ); + + VERIFY( ranges::lexicographical_compare(rx, ry, ranges::greater{}, + std::negate<>{}, + std::negate<>{}) ); + VERIFY( !ranges::lexicographical_compare(ry, rx, ranges::greater{}, + std::negate<>{}, + std::negate<>{}) ); +} + +void +test02() +{ + int x[] = {1, 2, 3, 4, 5}; + int y[] = {1, 2, 3, 5}; + int z[] = {1, 2, 3, 4, 5, 6}; + + VERIFY( ranges::lexicographical_compare(x, y) ); + VERIFY( !ranges::lexicographical_compare(y, x) ); + + VERIFY( ranges::lexicographical_compare(x, z) ); + VERIFY( !ranges::lexicographical_compare(z, x) ); + + VERIFY( !ranges::lexicographical_compare(x, x) ); + + VERIFY( !ranges::lexicographical_compare(x, y, {}, + std::negate<>{}, + std::negate<>{}) ); + VERIFY( ranges::lexicographical_compare(y, x, {}, + std::negate<>{}, + std::negate<>{}) ); + + VERIFY( ranges::lexicographical_compare(x, z, ranges::greater{}) ); + VERIFY( !ranges::lexicographical_compare(z, x, ranges::greater{}) ); + + VERIFY( ranges::lexicographical_compare(x, y, ranges::greater{}, + std::negate<>{}, + std::negate<>{}) ); + VERIFY( !ranges::lexicographical_compare(y, x, ranges::greater{}, + std::negate<>{}, + std::negate<>{}) ); +} + +void +test03() +{ + int x[] = {1, 2, 3, 4, 5}; + int y[] = {1, 2, 5, 3}; + int z[] = {1, 2, 3, 5}; + + do + { + VERIFY( ranges::lexicographical_compare(x, y) ); + VERIFY( !ranges::lexicographical_compare(x, y, ranges::greater{}) ); + VERIFY( !ranges::lexicographical_compare(y, x) ); + VERIFY( ranges::lexicographical_compare(y, x, ranges::greater{}) ); + + test_container cy(y); + VERIFY( ranges::lexicographical_compare(x, cy) ); + VERIFY( !ranges::lexicographical_compare(x, cy, ranges::greater{}) ); + VERIFY( !ranges::lexicographical_compare(cy, x) ); + VERIFY( ranges::lexicographical_compare(cy, x, ranges::greater{}) ); + + test_container cz(z); + VERIFY( ranges::lexicographical_compare(cz.begin(), cz.end(), + cy.begin(), cy.end()) ); + VERIFY( !ranges::lexicographical_compare(cy.begin(), cy.end(), + cz.begin(), cz.end()) ); + + std::vector vx(x, x+5), vy(y, y+5); + VERIFY( ranges::lexicographical_compare(vx, vy) ); + VERIFY( !ranges::lexicographical_compare(vx, vy, ranges::greater{}) ); + VERIFY( !ranges::lexicographical_compare(vy, vx) ); + VERIFY( ranges::lexicographical_compare(vy, vx, ranges::greater{}) ); + } while (ranges::next_permutation(y).found); +} + +constexpr bool +test04() +{ + int x[] = {1}; + int y[] = {1}; + return (ranges::lexicographical_compare((int[]){1,2,3,5}, + (int[]){1,2,4}) + && !ranges::lexicographical_compare(x, x, y, y)); +} + +int +main() +{ + test01(); + test02(); + test03(); + static_assert(test04()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/lower_bound/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/lower_bound/constrained.cc new file mode 100644 index 00000000000..df93f41e823 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/lower_bound/constrained.cc @@ -0,0 +1,66 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1, 2, 3, 4, 5, 5, 6, 7}; + for (unsigned i = 0; i < 5; i++) + for (unsigned j = 5; j < 8; j++) + { + test_container cx(x); + auto result = ranges::lower_bound(std::next(cx.begin(), i), + std::next(cx.begin(), j), + 4, {}, [] (int a) { return a-1; }); + VERIFY( result.ptr == x+4 ); + } + + ranges::reverse(x); + test_range rx(x); + auto result = ranges::lower_bound(rx, 5, ranges::greater{}, + [] (int a) { return a+1; }); + VERIFY( result.ptr == x+4 ); +} + +constexpr bool +test02() +{ + int x[] = {1, 2, 3, 4, 5}; + return (ranges::lower_bound(x, 6) == x+5 + && ranges::lower_bound(x, x, 6) == x + && ranges::lower_bound(x, 1) == x); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc new file mode 100644 index 00000000000..3fcdb3a366c --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/max/constrained.cc @@ -0,0 +1,82 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i, j; +}; + +void +test01() +{ + VERIFY( ranges::max(1, 2) == 2); + VERIFY( ranges::max(2, 1) == 2); + VERIFY( ranges::max(1, 2, ranges::greater{}) == 1); + VERIFY( ranges::max(1, 2, ranges::greater{}, std::negate<>{}) == 2); + VERIFY( ranges::max(1, 2, {}, std::negate<>{}) == 1); + VERIFY( ranges::max(X{1,2}, X{1,3}, {}, &X::i).j == 2 ); +} + +void +test02() +{ + int x[] = {1,2,3,4}; + do + { + test_range cx(x); + VERIFY( ranges::max(cx) == 4 ); + cx.bounds.first = x; + VERIFY( ranges::max(cx, ranges::greater{}) == 1 ); + cx.bounds.first = x; + VERIFY( ranges::max(cx, {}, std::negate<>{}) == 1); + cx.bounds.first = x; + VERIFY( ranges::max(cx, ranges::greater{}, std::negate<>{}) == 4 ); + } while (ranges::next_permutation(x).found); + + constexpr X y[] = {{0,5},{1,2},{1,3}}; + static_assert(ranges::max(y, {}, &X::i).j == 2); +} + +void +test03() +{ + VERIFY( ranges::max({2,3,1,4}) == 4 ); + VERIFY( ranges::max({2,3,1,4}, ranges::greater{}) == 1 ); + VERIFY( ranges::max({2,3,1,4}, {}, std::negate<>{}) == 1 ); + VERIFY( ranges::max({2,3,1,4}, ranges::greater{}, std::negate<>{}) == 4 ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/max_element/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/max_element/constrained.cc new file mode 100644 index 00000000000..427faedbc44 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/max_element/constrained.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i, j; +}; + +void +test01() +{ + int x[] = {1,2,3,4}; + do + { + test_range cx(x); + VERIFY( *ranges::max_element(cx) == 4 ); + VERIFY( *ranges::max_element(cx, ranges::greater{}) == 1 ); + VERIFY( *ranges::max_element(cx, {}, std::negate<>{}) == 1); + VERIFY( *ranges::max_element(cx, ranges::greater{}, std::negate<>{}) == 4 ); + } while (ranges::next_permutation(x).found); + + test_container cx(x); + VERIFY( ranges::max_element(cx.begin(), cx.begin()) == cx.begin() ); + + constexpr X y[] = {{0,5},{1,2},{1,3}}; + static_assert(ranges::max_element(y, y+3, {}, &X::i)->j == 2); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/merge/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/merge/constrained.cc new file mode 100644 index 00000000000..3f3a0f79f9b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/merge/constrained.cc @@ -0,0 +1,75 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1,2,3,4,5}; + for (int i = 0; i <= 5; i++) + for (int j = 0; j <= 5; j++) + { + int z[10]; + test_range rx(x, x+i), ry(x, x+j); + test_range rz(z, z+i+j); + auto [in1,in2,out] = ranges::merge(rx, ry, rz.begin()); + VERIFY( in1 == rx.end() ); + VERIFY( in2 == ry.end() ); + VERIFY( out == rz.end() ); + + std::vector v(x, x+i); + v.insert(v.end(), x, x+j); + ranges::sort(v); + + VERIFY( ranges::equal(v.begin(), v.end(), z, z+i+j) ); + } +} + +constexpr bool +test02() +{ + int x[] = {-1,-3,-5}; + int y[] = {2,4,6}; + int z[6]; + ranges::merge(x, x+3, y, y+3, z, + ranges::greater{}, {}, [] (int a) { return -a; }); + + const int w[6] = {-1, 2, -3, 4, -5, 6}; + return ranges::equal(w, z); +} + + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc new file mode 100644 index 00000000000..c3a83b975c9 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/min/constrained.cc @@ -0,0 +1,82 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i, j; +}; + +void +test01() +{ + VERIFY( ranges::min(1, 2) == 1); + VERIFY( ranges::min(2, 1) == 1); + VERIFY( ranges::min(1, 2, ranges::greater{}) == 2); + VERIFY( ranges::min(1, 2, ranges::greater{}, std::negate<>{}) == 1); + VERIFY( ranges::min(1, 2, {}, std::negate<>{}) == 2); + VERIFY( ranges::min(X{1,2}, X{1,3}, {}, &X::i).j == 2 ); +} + +void +test02() +{ + int x[] = {1,2,3,4}; + do + { + test_range cx(x); + VERIFY( ranges::min(cx) == 1 ); + cx.bounds.first = x; + VERIFY( ranges::min(cx, ranges::greater{}) == 4 ); + cx.bounds.first = x; + VERIFY( ranges::min(cx, {}, std::negate<>{}) == 4); + cx.bounds.first = x; + VERIFY( ranges::min(cx, ranges::greater{}, std::negate<>{}) == 1 ); + } while (ranges::next_permutation(x).found); + + constexpr X y[] = {{5,0},{1,2},{1,3}}; + static_assert(ranges::min(y, {}, &X::i).j == 2); +} + +void +test03() +{ + VERIFY( ranges::min({2,3,1,4}) == 1 ); + VERIFY( ranges::min({2,3,1,4}, ranges::greater{}) == 4 ); + VERIFY( ranges::min({2,3,1,4}, {}, std::negate<>{}) == 4 ); + VERIFY( ranges::min({2,3,1,4}, ranges::greater{}, std::negate<>{}) == 1 ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/min_element/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/min_element/constrained.cc new file mode 100644 index 00000000000..518060522a3 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/min_element/constrained.cc @@ -0,0 +1,60 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i, j; +}; + +void +test01() +{ + int x[] = {1,2,3,4}; + do + { + test_range cx(x); + VERIFY( *ranges::min_element(cx) == 1 ); + VERIFY( *ranges::min_element(cx, ranges::greater{}) == 4 ); + VERIFY( *ranges::min_element(cx, {}, std::negate<>{}) == 4); + VERIFY( *ranges::min_element(cx, ranges::greater{}, std::negate<>{}) == 1 ); + } while (ranges::next_permutation(x).found); + + test_container cx(x); + VERIFY( ranges::min_element(cx.begin(), cx.begin()) == cx.begin() ); + + constexpr X y[] = {{5,0},{1,2},{1,3}}; + static_assert(ranges::min_element(y, y+3, {}, &X::i)->j == 2); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/minmax/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/minmax/constrained.cc new file mode 100644 index 00000000000..aa9364ab04c --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/minmax/constrained.cc @@ -0,0 +1,98 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; + +namespace ranges = std::ranges; + +template +constexpr bool +operator==(const ranges::minmax_result& lhs, + const ranges::minmax_result& rhs) +{ + return (lhs.min == rhs.min + && rhs.max == rhs.max); +} + + +struct X +{ + int i, j; +}; + +using res_t = ranges::minmax_result; + +void +test01() +{ + VERIFY( ranges::minmax(1, 2) == res_t(1,2) ); + VERIFY( ranges::minmax(2, 1) == res_t(1,2) ); + VERIFY( ranges::minmax(1, 2, ranges::greater{}) == res_t(2,1) ); + VERIFY( ranges::minmax(1, 2, ranges::greater{}, std::negate<>{}) == res_t(1,2) ); + VERIFY( ranges::minmax(1, 2, {}, std::negate<>{}) == res_t(2,1) ); + VERIFY( ranges::minmax(X{1,2}, X{1,3}, {}, &X::i).min.j == 2 ); + VERIFY( ranges::minmax(X{1,2}, X{1,3}, {}, &X::i).max.j == 3 ); +} + +void +test02() +{ + int x[] = {1,2,3,4}; + do + { + test_range cx(x); + VERIFY( ranges::minmax(cx) == res_t(1,4) ); + cx.bounds.first = x; + VERIFY( ranges::minmax(cx, ranges::greater{}) == res_t(4,1) ); + cx.bounds.first = x; + VERIFY( ranges::minmax(cx, {}, std::negate<>{}) == res_t(4,1)); + cx.bounds.first = x; + VERIFY( ranges::minmax(cx, ranges::greater{}, std::negate<>{}) + == res_t(1,4) ); + } while (ranges::next_permutation(x).found); + + constexpr X y[] = {{1,5},{1,2},{1,3}}; + static_assert(ranges::minmax(y, {}, &X::i).min.j == 5); + static_assert(ranges::minmax(y, {}, &X::i).max.j == 3); +} + +void +test03() +{ + VERIFY( ranges::minmax({2,3,1,4}) == res_t(1,4) ); + VERIFY( ranges::minmax({2,3,1,4}, ranges::greater{}) == res_t(4,1) ); + VERIFY( ranges::minmax({2,3,1,4}, {}, std::negate<>{}) == res_t(4,1) ); + VERIFY( ranges::minmax({2,3,1,4}, ranges::greater{}, std::negate<>{}) + == res_t(1,4) ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/minmax_element/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/minmax_element/constrained.cc new file mode 100644 index 00000000000..40019c43326 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/minmax_element/constrained.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i, j; +}; + +void +test01() +{ + int x[] = {1,2,3,4}; + do + { + test_range cx(x); + VERIFY( *ranges::minmax_element(cx).min == 1 ); + VERIFY( *ranges::minmax_element(cx).max == 4 ); + VERIFY( *ranges::minmax_element(cx, ranges::greater{}).min == 4 ); + VERIFY( *ranges::minmax_element(cx, ranges::greater{}).max == 1 ); + VERIFY( *ranges::minmax_element(cx, {}, std::negate<>{}).min == 4); + VERIFY( *ranges::minmax_element(cx, {}, std::negate<>{}).max == 1); + VERIFY( *ranges::minmax_element(cx, ranges::greater{}, std::negate<>{}).min + == 1 ); + VERIFY( *ranges::minmax_element(cx, ranges::greater{}, std::negate<>{}).max + == 4 ); + } while (ranges::next_permutation(x).found); + + test_container cx(x); + VERIFY( ranges::minmax_element(cx.begin(), cx.begin()).min == cx.begin() ); + VERIFY( ranges::minmax_element(cx.begin(), cx.begin()).max == cx.begin() ); + + constexpr X y[] = {{1,5},{1,2},{1,3}}; + static_assert(ranges::minmax_element(y, y+3, {}, &X::i).min->j == 5); + static_assert(ranges::minmax_element(y, y+3, {}, &X::i).max->j == 3); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/mismatch/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/mismatch/constrained.cc new file mode 100644 index 00000000000..37e79a2d62f --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/mismatch/constrained.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X xa[] = { {1}, {2}, {3}, {4}, {5}, {6} }; + X xb[] = { {1}, {2}, {3}, {3}, {5}, {6} }; + auto res = ranges::mismatch(xa, xa+6, xb, xb+6, {}, &X::i, &X::i); + VERIFY( res.in1 == xa+3 && res.in2 == xb+3 ); + + test_container ca(xa); + test_container cb(xb); + auto res2 = ranges::mismatch(ca, cb, {}, &X::i, &X::i); + VERIFY( res2.in1->i == 4 && res2.in2->i == 3 ); + res2 = ranges::mismatch(ca, ca, {}, &X::i, &X::i); + VERIFY( res2.in1 == ranges::end(ca) && res2.in2 == ranges::end(ca) ); + + test_range ra(xa); + test_range rb(xb); + auto res3 = ranges::mismatch(ra, rb, {}, &X::i, &X::i); + VERIFY( res3.in1->i == 4 && res3.in2->i == 3 ); + + test_range ra2(xa); + ra.bounds.first = xa; + res3 = ranges::mismatch(ra, ra2, {}, &X::i, &X::i); + VERIFY( res3.in1 == ranges::end(ra) && res3.in2 == ranges::end(ra2) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y ya[] = { {1,2}, {2,4}, {3,6}, {1,6} }; + static constexpr Y yb[] = { {2,1}, {4,2}, {4,2}, {7,1} }; + static_assert(ranges::mismatch(ya, yb, {}, &Y::i, &Y::j).in1 == ya+2); + static_assert(ranges::mismatch(ya, yb, {}, &Y::i, &Y::j).in2 == yb+2); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc new file mode 100644 index 00000000000..d205b3572a1 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/move/constrained.cc @@ -0,0 +1,203 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + int moved = 0; + + constexpr X() : i(0) { } + constexpr X(int a) : i(a) { } + + constexpr X(const X&) = delete; + constexpr X& operator=(const X&) = delete; + + constexpr X(X&& other) + { + *this = std::move(other); + } + + constexpr X& + operator=(X&& other) + { + other.moved++; + i = other.i; + return *this; + } + + friend constexpr bool + operator==(const X& a, const X& b) + { return a.i == b.i; } +}; + +void +test01() +{ + { + X x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + X y[7] = { 0, 0, 0, 0, 0, 0, 0 }; + X z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + auto [in, out] = ranges::move(x, y); + VERIFY( ranges::equal(x, y) && in == x+7 && out == y+7 ); + VERIFY( ranges::equal(x, z) ); + } + + { + int x[3] = { 1, 2, 3 }; + char y[4] = { 0 }; + int z[3] = { 1, 2, 3 }; + test_container cx(x); + test_container cy(y); + auto [in, out] = ranges::move(cx, cy.begin()); + VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 ); + VERIFY( ranges::equal(x, z) ); + } + + { + char x[3] = { 1, 2, 3 }; + int y[4] = { 0 }; + int z[3] = { 1, 2, 3 }; + test_range cx(x); + test_range cy(y); + auto [in, out] = ranges::move(cx, ranges::begin(cy)); + VERIFY( ranges::equal(x, x+3, y, y+3) && in.ptr == x+3 && out.ptr == y+3 ); + VERIFY( ranges::equal(x, z) ); + } + + { + std::vector x= {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::move(x, ranges::begin(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::move(x, ranges::begin(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::move(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.end())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::move(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.end())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } +} + +void +test02() +{ + X x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + X z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::move(x, y); + VERIFY( ranges::equal(x, x+5, y, y+5) ); + VERIFY( in == x+5 ); + VERIFY( out == y+5 ); + VERIFY( y[5].i == 2 ); + VERIFY( ranges::equal(x, z) ); + VERIFY( ranges::count(x, 1, &X::moved) == 5 ); + VERIFY( ranges::count(y, 0, &X::moved) == 6 ); +} + +constexpr bool +test03() +{ + bool ok = true; + X x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + X z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::move(x, y); + ok &= ranges::equal(x, x+5, y, y+5); + ok &= (in == x+5); + ok &= (out == y+5); + ok &= (y[5].i == 2); + ok &= ranges::equal(x, z); + ok &= ranges::count(x, 1, &X::moved) == 5; + ok &= ranges::count(y, 0, &X::moved) == 6; + return ok; +} + +void +test04() +{ + X x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + X z[] = { {2}, {2}, {6}, {8}, {10} }; + test_range rx(x); + auto [in, out] = ranges::move(std::move_iterator{ranges::begin(rx)}, + std::move_sentinel{ranges::end(rx)}, + ranges::begin(y)); + VERIFY( ranges::equal(x, x+5, y, y+5) ); + VERIFY( std::move(in).base().ptr == x+5 ); + VERIFY( out == y+5 ); + VERIFY( y[5].i == 2 ); + VERIFY( ranges::equal(x, z) ); + VERIFY( ranges::count(x, 1, &X::moved) == 5 ); + VERIFY( ranges::count(y, 0, &X::moved) == 6 ); +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); + test04(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc new file mode 100644 index 00000000000..3c4aa5dc70d --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/move_backward/constrained.cc @@ -0,0 +1,170 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + int moved = 0; + + constexpr X() : i(0) { } + constexpr X(int a) : i(a) { } + + constexpr X(const X&) = delete; + constexpr X& operator=(const X&) = delete; + + constexpr X(X&& other) + { + *this = std::move(other); + } + + constexpr X& + operator=(X&& other) + { + other.moved++; + i = other.i; + return *this; + } + + friend constexpr bool + operator==(const X& a, const X& b) + { return a.i == b.i; } +}; + +void +test01() +{ + { + X x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + X y[7] = { 0, 0, 0, 0, 0, 0, 0 }; + X z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + auto [in, out] = ranges::move_backward(x, y+7); + VERIFY( ranges::equal(x, y) && in == x+7 && out == y ); + VERIFY( ranges::equal(x, z) ); + } + + { + int x[3] = { 1, 2, 3 }; + char y[4] = { 0 }; + int z[3] = { 1, 2, 3 }; + test_container cx(x); + test_container cy(y); + auto [in, out] = ranges::move_backward(cx, cy.end()); + VERIFY( ranges::equal(x, x+3, y+1, y+4) && in.ptr == x+3 && out.ptr == y+1 ); + VERIFY( ranges::equal(x, z) ); + } + + { + std::vector x= {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::move_backward(x, ranges::end(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in, out] = ranges::move_backward(x, ranges::end(y)); + VERIFY( in.base() == x.data()+3 ); + VERIFY( out.base() == y.data() ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::move_backward(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.begin())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } + + { + std::vector x = {1,2,3}; + std::vector y(3); + const int z[3] = { 1, 2, 3 }; + auto [in,out] = ranges::move_backward(make_reverse_iterator(x.end()), + make_reverse_iterator(x.begin()), + make_reverse_iterator(y.begin())); + VERIFY( in.base().base() == x.data()+3 ); + VERIFY( out.base().base() == y.data()+3 ); + VERIFY( ranges::equal(y, z) && ranges::equal(x, z) ); + } +} + +void +test02() +{ + X x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + const X z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::move_backward(x, ranges::end(y)); + VERIFY( ranges::equal(x, x+5, y+1, y+6) ); + VERIFY( in == x+5 ); + VERIFY( out == y+1 ); + VERIFY( y[0].i == 2 ); + VERIFY( ranges::equal(x, z) ); + VERIFY( ranges::count(x, 1, &X::moved) == 5 ); + VERIFY( ranges::count(y, 0, &X::moved) == 6 ); +} + +constexpr bool +test03() +{ + bool ok = true; + X x[] = { {2}, {2}, {6}, {8}, {10} }; + X y[] = { {2}, {6}, {8}, {10}, {11}, {2} }; + const X z[] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::move_backward(x, ranges::end(y)); + ok &= ranges::equal(x, x+5, y+1, y+6); + ok &= (in == x+5); + ok &= (out == y+1); + ok &= (y[0].i == 2); + ok &= ranges::equal(x, z); + ok &= ranges::count(x, 1, &X::moved) == 5; + ok &= ranges::count(y, 0, &X::moved) == 6; + return ok; +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc new file mode 100644 index 00000000000..e69b551a56b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/next_permutation/constrained.cc @@ -0,0 +1,83 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1, 2, 3, 4, 5}; + int y[] = {1, 2, 3, 4, 5}; + + for (int i = 0; i <= 5; i++) + { + test_container cx(x, x+i); + test_container cy(y, y+i); + for (int j = 0; ; j++) + { + auto found1 = std::next_permutation(cx.begin(), cx.end()); + auto [found2,last] = ranges::next_permutation(cy.begin(), cy.end()); + VERIFY( found1 == found2 ); + VERIFY( ranges::equal(cx, cy) ); + if (!found2) + break; + } + } +} + +void +test02() +{ + int x[] = {5, 4, 3, 2, 1}; + test_range rx(x); + auto [found,last] = ranges::next_permutation(rx, ranges::greater{}); + VERIFY( found && last == rx.end() ); + VERIFY( last == rx.end() ); + VERIFY( ranges::equal(rx, (int[]){5,4,3,1,2}) ); + ranges::next_permutation(rx, {}, [] (int a) { return -a; }); + VERIFY( ranges::equal(rx, (int[]){5,4,2,3,1}) ); + + VERIFY( !ranges::next_permutation(x, x).found ); + VERIFY( !ranges::next_permutation(x, x+1).found ); +} + +constexpr bool +test03() +{ + int x[] = {1,2,3}; + ranges::next_permutation(x); + return ranges::equal(x, (int[]){1,3,2}); +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/none_of/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/none_of/constrained.cc new file mode 100644 index 00000000000..55617a97a7b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/none_of/constrained.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +struct XLess +{ + int val; + bool operator()(X& x) const { return x.i < val; } +}; + +struct ILess +{ + int val; + bool operator()(int& i) const { return i < val; } +}; + +template +struct NotZero +{ + bool operator()(T& t) const { return t != 0; } +}; + +void +test01() +{ + X x[] = { {2}, {4}, {6}, {8}, {10}, {11} }; + + VERIFY( !ranges::none_of(x, x+6, XLess{3}) ); + VERIFY( !ranges::none_of(x, x+6, ILess{3}, &X::i) ); + VERIFY( ranges::none_of(x+1, x+6, XLess{3}) ); + VERIFY( ranges::none_of(x+1, x+6, ILess{3}, &X::i) ); + VERIFY( !ranges::none_of(x, XLess{5}) ); + VERIFY( !ranges::none_of(x, ILess{5}, &X::i) ); + + test_container c(x); + VERIFY( !ranges::none_of(c, NotZero{}, &X::i) ); + + test_range r(x); + VERIFY( !ranges::none_of(r, NotZero{}, &X::i) ); + VERIFY( !ranges::none_of(r, NotZero{}, [](X& x) { return &x; }) ); +} + +struct Y { int i; int j; }; + +void +test02() +{ + static constexpr Y y[] = { {1,2}, {2,4}, {3,6} }; + static_assert(!ranges::none_of(y, [](int i) { return i%2 == 0; }, &Y::i)); + static_assert(!ranges::none_of(y, [](const Y& y) { return y.i + y.j == 3; })); + static_assert(ranges::none_of(y, [](const Y& y) { return y.i == y.j; })); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc new file mode 100644 index 00000000000..34f3013b199 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/nth_element/constrained.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[50]; + std::iota(x, x+50, 0); + + auto pred = std::greater{}; + auto proj = [] (int a) { return -a; }; + for (int i = 0; i < 50; i++) + { + test_range rx(x); + std::ranlux48_base g(i); + ranges::shuffle(rx, g); + + auto result = ranges::nth_element(rx, rx.begin()+i, pred, proj); + VERIFY( result == rx.end() ); + VERIFY( x[i] == i ); + for (int j = 0; j < i; j++) + for (int k = i; k < 50; k++) + VERIFY( !pred(proj(x[k]), proj(x[j])) ); + + result = ranges::nth_element(rx, rx.begin()+i, pred); + VERIFY( result == rx.end() ); + VERIFY( x[i] == 49-i ); + for (int j = 0; j < i; j++) + for (int k = i; k < 50; k++) + VERIFY( !pred(x[k], x[j]) ); + } +} + +constexpr bool +test02() +{ + int x[] = {5,2,1,3,4}; + ranges::nth_element(x, x+3); + return x[3] == 4; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc new file mode 100644 index 00000000000..430e3c0b61b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort/constrained.cc @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + for (unsigned size = 0; size < 50; ++size) + { + std::vector vref(size); + std::iota(vref.begin(), vref.end(), 0); + std::vector v1(vref), v2(vref); + test_container c + = {&v1[0], &v1[0] + size}; + test_range r + = {&v2[0], &v2[0] + size}; + + std::ranlux48_base g1(size), g2(size + 1); + ranges::shuffle(c, g1); + ranges::shuffle(ranges::begin(r), ranges::end(r), g2); + + for (unsigned middle = 0; middle < std::min(size, 10U); ++middle) + { + auto res1 = ranges::partial_sort(c.begin(), c.begin()+middle, c.end(), + {}, std::negate<>{}); + VERIFY( res1 == c.end() ); + + auto res2 = ranges::partial_sort(r, + ranges::begin(r)+middle, + ranges::greater{}); + VERIFY( res2 == ranges::end(r) ); + + VERIFY( ranges::equal(c.begin(), c.begin()+middle, + r.begin(), r.begin()+middle) ); + VERIFY( ranges::equal(c.begin(), c.begin()+middle, + vref.rbegin(), vref.rbegin()+middle) ); + } + } +} + +constexpr bool +test02() +{ + int x[] = { 5,4,1,3,2 }; + const int y[] = { 1,2,3 }; + ranges::partial_sort(x, x+3, x+5); + return ranges::equal(x, x+3, y, y+3); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc new file mode 100644 index 00000000000..6b586f885dd --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/partial_sort_copy/constrained.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + for (unsigned size = 0; size < 50; ++size) + { + std::vector vref(size); + std::iota(vref.begin(), vref.end(), 0); + std::vector v1(vref), v2(vref); + + std::ranlux48_base g1(size), g2(size + 1); + ranges::shuffle(v1, g1); + ranges::shuffle(v2, g2); + + for (unsigned middle = 0; middle < 10; ++middle) + { + test_container c + = {&v1[0], &v1[0] + size}; + test_range r + = {&v2[0], &v2[0] + size}; + + std::vector o1(middle), o2(middle); + test_range w1 + = {&o1[0], &o1[0]+middle}; + test_range w2 + = {&o2[0], &o2[0]+middle}; + + auto [in1, out1] = ranges::partial_sort_copy(c.begin(), c.end(), + w1.begin(), w1.end(), + {}, + std::negate<>{}, + std::negate<>{}); + VERIFY( in1 == c.end() ); + VERIFY( out1 == w1.begin() + std::min(size, middle) ); + + auto [in2,out2] = ranges::partial_sort_copy(r, w2, ranges::greater{}); + VERIFY( in2 == ranges::end(r) ); + VERIFY( out2 == w2.begin() + std::min(size, middle) ); + + VERIFY( ranges::equal(w1.begin(), out1, w2.begin(), out2) ); + VERIFY( ranges::equal(w1.begin(), out1, + vref.rbegin(), + vref.rbegin()+(out1-w1.begin())) ); + } + } +} + +constexpr bool +test02() +{ + int x[] = { 5,4,1,3,2 }; + int w[3]; + const int y[] = { 1,2,3 }; + ranges::partial_sort_copy(x, x+5, w, w+3); + return ranges::equal(w, y); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/partition/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/partition/constrained.cc new file mode 100644 index 00000000000..4e5fa5e32cd --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/partition/constrained.cc @@ -0,0 +1,71 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +template typename wrapper> +void +test01() +{ + { + int x[] = {1,2,3,4,5,6,7,8,9,10}; + test_container cx(x); + auto range = ranges::partition(cx, [] (int a) { return a%2==0; }); + VERIFY( range.begin().ptr == x+5 ); + VERIFY( range.end().ptr == x+10 ); + VERIFY( ranges::is_partitioned(cx, [] (int a) { return a%2==0; }) ); + } + + { + int x[] = {1,2,3,4,5,6,7,8}; + test_range rx(x); + auto range = ranges::partition(rx, + [] (int a) { return a%2==0; }, + [] (int a) { return a+1; }); + VERIFY( range.begin().ptr == x+4 ); + VERIFY( range.end().ptr == x+8 ); + VERIFY( ranges::is_partitioned(rx, [] (int a) { return a%2==1; }) ); + } +} + +constexpr bool +test02() +{ + int x[] = {1,2,3,4,5,6,7,8,9,10}; + auto range = ranges::partition(x, x+9, [] (int a) { return a < 100; }); + return (range.begin() == x+9 && range.end() == x+9); +} + +int +main() +{ + test01(); + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/partition_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/partition_copy/constrained.cc new file mode 100644 index 00000000000..8ed6e24d451 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/partition_copy/constrained.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + { + int x[] = {1,2,3,4,5,6,7,8,9,10,11}; + int y[5], z[6]; + test_container cx(x); + test_container cy(y), cz(z); + auto pred = [] (int a) { return a%2==0; }; + auto [in,out_true,out_false] + = ranges::partition_copy(cx, cy.begin(), cz.begin(), pred); + VERIFY( in.ptr == x+11 ); + VERIFY( out_true.ptr == y+5 ); + VERIFY( out_false.ptr == z+6 ); + VERIFY( ranges::all_of(cy, pred) ); + VERIFY( ranges::none_of(cz, pred) ); + } + + { + int x[] = {1,2,3,4,5,6,7,8,9,10,11}; + int y[6], z[5]; + test_range cx(x); + test_range cy(y), cz(z); + auto pred = [] (int a) { return a%2==0; }; + auto proj = [] (int a) { return a+1; }; + auto [in,out_true,out_false] + = ranges::partition_copy(cx, cy.begin(), cz.begin(), pred, proj); + VERIFY( in.ptr == x+11 ); + VERIFY( out_true.ptr == y+6 ); + VERIFY( out_false.ptr == z+5 ); + VERIFY( ranges::none_of(y, pred) ); + VERIFY( ranges::all_of(z, pred) ); + } +} + +constexpr bool +test02() +{ + int x[] = {1,2,3,4,5,6,7,8,9,10}; + auto range = ranges::partition(x, x+9, [] (int a) { return a < 100; }); + return (range.begin() == x+9 && range.end() == x+9); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/partition_point/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/partition_point/constrained.cc new file mode 100644 index 00000000000..2a430f23438 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/partition_point/constrained.cc @@ -0,0 +1,67 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + for (int k = 1; k <= 7; k++) + { + int x[] = {1,2,3,4,5,6,7}; + test_container cx(x); + auto pred = [&] (int a) { return a <= k; }; + auto middle = ranges::partition_point(cx, pred); + VERIFY( middle.ptr == x+k ); + } + + for (int k = 1; k <= 8; k++) + { + int x[] = {1,2,3,4,5,6,7,8}; + test_range rx(x); + auto pred = [&] (int a) { return a > -k; }; + auto proj = [] (int a) { return -a; }; + auto middle = ranges::partition_point(rx, pred, proj); + VERIFY( middle.ptr == x+k-1 ); + } +} + +constexpr bool +test02() +{ + int x[] = {1,2,3,4,5}; + return (ranges::partition_point(x, x+5, [] (int a) { return a < 6; }) == x+5 + && ranges::partition_point(x, x+5, [] (int a) { return a < 0; }) == x); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc new file mode 100644 index 00000000000..25bbad9be0c --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/prev_permutation/constrained.cc @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {5, 4, 3, 2, 1}; + int y[] = {5, 4, 3, 2, 1}; + + for (int i = 0; i <= 5; i++) + { + test_container cx(x, x+i); + test_container cy(y, y+i); + for (int j = 0; ; j++) + { + auto found1 = std::prev_permutation(cx.begin(), cx.end()); + auto [found2,last] = ranges::prev_permutation(cy.begin(), cy.end()); + VERIFY( found1 == found2 ); + VERIFY( ranges::equal(cx, cy) ); + if (!found2) + break; + } + } +} + +void +test02() +{ + int x[] = {1, 2, 3, 4, 5}; + test_range rx(x); + auto [found,last] = ranges::prev_permutation(rx, ranges::greater{}); + VERIFY( found && last == rx.end() ); + VERIFY( last == rx.end() ); + VERIFY( ranges::equal(rx, (int[]){1,2,3,5,4}) ); + ranges::prev_permutation(rx, {}, [] (int a) { return -a; }); + VERIFY( ranges::equal(rx, (int[]){1,2,4,3,5}) ); + + VERIFY( !ranges::prev_permutation(x, x).found ); + VERIFY( !ranges::prev_permutation(x, x+1).found ); +} + +constexpr bool +test03() +{ + int x[] = {3,2,1}; + ranges::prev_permutation(x); + return ranges::equal(x, (int[]){3,1,2}); +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} + diff --git a/libstdc++-v3/testsuite/25_algorithms/remove/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/remove/constrained.cc new file mode 100644 index 00000000000..39a002f3cb6 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/remove/constrained.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; +}; + +void +test01() +{ + int x[5] = { 1, 2, 3, 4, 5 }; + const int y[4] = { 1, 2, 4, 5 }; + auto res = ranges::remove(x, 3); + VERIFY( res.begin() == x+4 && res.end() == x+5 ); + VERIFY( ranges::equal(x, x+4, y, y+4) ); +} + +void +test02() +{ + int x[1]; + test_container c(x, x); + auto res = ranges::remove(c, 1); + VERIFY( res.begin().ptr == x && res.end().ptr == x ); +} + +void +test03() +{ + int x[1] = {1}; + test_container c(x); + auto res = ranges::remove(c, 0); + VERIFY( res.begin().ptr == x+1 && res.end().ptr == x+1 ); + res = ranges::remove(c, 1); + VERIFY( res.begin().ptr == x && res.end().ptr == x+1 ); +} + +void +test04() +{ + X x[8] = { {0}, {1}, {0}, {1}, {0}, {0}, {1}, {1} }; + const int y[4] = { 0, 0, 0, 0 }; + test_container c(x); + auto res = ranges::remove(c, 1, &X::i); + VERIFY( res.begin().ptr == x+4 && res.end().ptr == x+8 ); + VERIFY( ranges::equal(x, x+4, y, y+4, {}, &X::i) ); +} + +constexpr bool +test05() +{ + int x[6] = { 3, 2, 3, 3, 5, 3 }; + const int y[2] = { 2, 5 }; + auto res = ranges::remove(x, 3); + return ranges::equal(x, res.begin(), y, y+2); +} + + +int +main() +{ + test01(); + test02(); + test03(); + test04(); + static_assert(test05()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/remove_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/remove_copy/constrained.cc new file mode 100644 index 00000000000..0cf65a727b8 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/remove_copy/constrained.cc @@ -0,0 +1,109 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + + friend constexpr bool + operator==(const X& a, const X& b) + { + return a.i == b.i; + } +}; + +void +test01() +{ + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[4]; + X z[4] = { {2}, {2}, {6}, {10} }; + auto [in,out] = ranges::remove_copy(x, x+5, y, 8, &X::i); + VERIFY( in == x+5 && out == y+4 ); + VERIFY( ranges::equal(y, z) ); + } + + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[5]; + X z[5] = { {2}, {2}, {6}, {8}, {10} }; + auto [in,out] = ranges::remove_copy(x, x+5, y, 11, &X::i); + VERIFY( in == x+5 && out == y+5 ); + VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {2} }; + X y[3]; + X z[3] = { {6}, {8}, {10} }; + test_container cx(x), cy(y), cz(z); + auto [in, out] = ranges::remove_copy(cx, cy.begin(), 2, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(cy, cz) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[4]; + const X z[4] = { {6}, {8}, {10}, {11} }; + test_range cx(x); + test_range cy(y); + auto [in, out] = ranges::remove_copy(cx, cy.begin(), 2, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(y, z) ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + bool ok = true; + Y x[3] = { {3,2}, {2,4}, {3,6} }; + Y y[1]; + Y z[1] = { {2,4} }; + auto [in, out] = ranges::remove_copy(x, y, 3, &Y::i); + ok &= in == x+3; + ok &= out == y+1; + ok &= ranges::equal(y, z, {}, &Y::i, &Y::i); + ok &= ranges::equal(y, z, {}, &Y::j, &Y::j); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/remove_copy_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/remove_copy_if/constrained.cc new file mode 100644 index 00000000000..b7c239ff397 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/remove_copy_if/constrained.cc @@ -0,0 +1,113 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + + friend constexpr bool + operator==(const X& a, const X& b) + { + return a.i == b.i; + } +}; + +void +test01() +{ + auto is_negative_p = [] (int a) { return a < 0; }; + auto is_two_p = [] (int a) { return a == 2; }; + + { + const X x[6] = { {2}, {2}, {6}, {8}, {2}, {11} }; + X y[2]; + X z[2] = { {6}, {8} }; + auto [in, out] = ranges::remove_copy_if(x, x+5, y, is_two_p, &X::i); + VERIFY( in == x+5 && out == y+2 ); + VERIFY( ranges::equal(y, z) ); + } + + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[5]; + X z[5] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::remove_copy_if(x, x+5, y, is_negative_p, &X::i); + VERIFY( in == x+5 && out == y+5 ); + VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[4]; + X z[4] = { {6}, {8}, {10}, {11} }; + test_container cx(x), cy(y), cz(z); + auto [in, out] = ranges::remove_copy_if(cx, cy.begin(), is_two_p, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(cy, cz) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[4]; + const X z[4] = { {6}, {8}, {10}, {11} }; + test_range cx(x); + test_range cy(y); + auto [in, out] = ranges::remove_copy_if(cx, cy.begin(), is_two_p, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(y, z) ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + bool ok = true; + Y x[3] = { {3,2}, {2,4}, {3,6} }; + Y y[1]; + Y z[1] = { {2,4} }; + auto [in, out] + = ranges::remove_copy_if(x, y, [] (int a) { return a%2 == 1; }, &Y::i); + ok &= in == x+3; + ok &= out == y+1; + ok &= ranges::equal(y, z, {}, &Y::i, &Y::i); + ok &= ranges::equal(y, z, {}, &Y::j, &Y::j); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc new file mode 100644 index 00000000000..1abc231ab93 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/remove_if/constrained.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; +}; + +void +test01() +{ + int x[5] = { 1, 2, 3, 4, 5 }; + const int y[4] = { 1, 2, 4, 5 }; + auto res = ranges::remove_if(x, [] (int a) { return a == 3; }); + VERIFY( res.begin() == x+4 && res.end() == x+5 ); + VERIFY( ranges::equal(x, x+4, y, y+4) ); +} + +void +test02() +{ + int x[1]; + test_container c(x, x); + auto res = ranges::remove_if(c, [] (int a) { return a == 1; }); + VERIFY( res.begin().ptr == x && res.end().ptr == x ); +} + +void +test03() +{ + int x[1] = {1}; + test_container c(x); + auto res = ranges::remove_if(c, [] (int a) { return a == 0; }); + VERIFY( res.begin().ptr == x+1 && res.end().ptr == x+1 ); + res = ranges::remove_if(c, [] (int a) { return a == 1; }); + VERIFY( res.begin().ptr == x && res.end().ptr == x+1 ); +} + +void +test04() +{ + X x[8] = { {0}, {1}, {0}, {1}, {0}, {0}, {1}, {1} }; + const int y[4] = { 0, 0, 0, 0 }; + test_range c(x); + auto res = ranges::remove_if(c, [] (int a) { return a == 1; }, &X::i); + VERIFY( res.begin().ptr == x+4 && res.end().ptr == x+8 ); + VERIFY( ranges::equal(x, x+4, y, y+4, {}, &X::i) ); +} + +constexpr bool +test05() +{ + int x[6] = { 3, 2, 3, 3, 5, 3 }; + const int y[2] = { 2, 5 }; + auto res = ranges::remove_if(x, [] (int a) { return a == 3; }); + return ranges::equal(x, res.begin(), y, y+2); +} + + +int +main() +{ + test01(); + test02(); + test03(); + test04(); + static_assert(test05()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/replace/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/replace/constrained.cc new file mode 100644 index 00000000000..3546872b72f --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/replace/constrained.cc @@ -0,0 +1,104 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + + friend constexpr bool + operator==(const X& a, const X& b) + { + return a.i == b.i; + } +}; + +void +test01() +{ + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6] = { {2}, {2}, {6}, {9}, {10}, {11} }; + auto res = ranges::replace(x, x+5, 8, X{9}, &X::i); + VERIFY( res == x+5 ); + VERIFY( ranges::equal(x, y) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + auto res = ranges::replace(x, x+5, 7, X{9}, &X::i); + VERIFY( res == x+5 ); + VERIFY( ranges::equal(x, y) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6] = { {7}, {7}, {6}, {8}, {10}, {11} }; + test_container cx(x), cy(y); + auto res = ranges::replace(cx, 2, X{7}, &X::i); + VERIFY( res == cx.end() ); + VERIFY( ranges::equal(cx, cy) ); + } + + { + int x[6] = { {2}, {2}, {6}, {8}, {10}, {2} }; + int y[6] = { {7}, {7}, {6}, {8}, {10}, {7} }; + test_range rx(x), ry(y); + auto res = ranges::replace(rx, 2, 7); + VERIFY( res == rx.end() ); + + rx.bounds.first = x; + ry.bounds.first = y; + VERIFY( ranges::equal(rx, ry) ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + bool ok = true; + Y x[] = { {3,2}, {2,4}, {3,6} }; + Y y[] = { {4,5}, {2,4}, {4,5} }; + auto res = ranges::replace(x, 3, Y{4,5}, &Y::i); + ok &= res == x+3; + ok &= ranges::equal(x, y, {}, &Y::i, &Y::i); + ok &= ranges::equal(x, y, {}, &Y::j, &Y::j); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/replace_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/replace_copy/constrained.cc new file mode 100644 index 00000000000..12e76a4cfdf --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/replace_copy/constrained.cc @@ -0,0 +1,109 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + + friend constexpr bool + operator==(const X& a, const X& b) + { + return a.i == b.i; + } +}; + +void +test01() +{ + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[5]; + X z[5] = { {2}, {2}, {6}, {9}, {10} }; + auto [in,out] = ranges::replace_copy(x, x+5, y, 8, X{9}, &X::i); + VERIFY( in == x+5 && out == y+5 ); + VERIFY( ranges::equal(y, z) ); + } + + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[5]; + X z[5] = { {2}, {2}, {6}, {8}, {10} }; + auto [in,out] = ranges::replace_copy(x, x+5, y, 7, X{9}, &X::i); + VERIFY( in == x+5 && out == y+5 ); + VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6]; + X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} }; + test_container cx(x), cy(y), cz(z); + auto [in, out] = ranges::replace_copy(cx, cy.begin(), 2, X{7}, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(cy, cz) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6]; + const X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} }; + test_range cx(x); + test_range cy(y); + auto [in, out] = ranges::replace_copy(cx, cy.begin(), 2, X{7}, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(y, z) ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + bool ok = true; + Y x[] = { {3,2}, {2,4}, {3,6} }; + Y y[] = { {4,5}, {2,4}, {4,5} }; + Y z[] = { {4,5}, {2,4}, {4,5} }; + auto [in, out] = ranges::replace_copy(x, y, 3, Y{4,5}, &Y::i); + ok &= in == x+3; + ok &= out == y+3; + ok &= ranges::equal(y, z, {}, &Y::i, &Y::i); + ok &= ranges::equal(y, z, {}, &Y::j, &Y::j); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/replace_copy_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/replace_copy_if/constrained.cc new file mode 100644 index 00000000000..9186a0a3d6c --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/replace_copy_if/constrained.cc @@ -0,0 +1,118 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + + friend constexpr bool + operator==(const X& a, const X& b) + { + return a.i == b.i; + } +}; + +void +test01() +{ + auto is_negative_p = [] (int a) { return a < 0; }; + auto is_two_p = [] (int a) { return a == 2; }; + + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[5]; + X z[5] = { {9}, {9}, {6}, {8}, {10} }; + auto [in, out] = ranges::replace_copy_if(x, x+5, y, + is_two_p, X{9}, &X::i); + VERIFY( in == x+5 && out == y+5 ); + VERIFY( ranges::equal(y, z) ); + } + + { + const X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[5]; + X z[5] = { {2}, {2}, {6}, {8}, {10} }; + auto [in, out] = ranges::replace_copy_if(x, x+5, y, + is_negative_p, X{9}, &X::i); + VERIFY( in == x+5 && out == y+5 ); + VERIFY( ranges::equal(x, x+5, y, y+5) && ranges::equal(y, z) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6]; + X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} }; + test_container cx(x), cy(y), cz(z); + auto [in, out] = ranges::replace_copy_if(cx, cy.begin(), + is_two_p, X{7}, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(cy, cz) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6]; + const X z[6] = { {7}, {7}, {6}, {8}, {10}, {11} }; + test_range cx(x); + test_range cy(y); + auto [in, out] = ranges::replace_copy_if(cx, cy.begin(), + is_two_p, X{7}, &X::i); + VERIFY( in == cx.end() && out == cy.end() ); + VERIFY( ranges::equal(y, z) ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + bool ok = true; + Y x[] = { {3,2}, {2,4}, {3,6} }; + Y y[] = { {4,5}, {2,4}, {4,5} }; + Y z[] = { {4,5}, {2,4}, {4,5} }; + auto [in, out] + = ranges::replace_copy_if(x, y, + [] (int a) { return a%2 == 1; }, Y{4,5}, &Y::i); + ok &= in == x+3; + ok &= out == y+3; + ok &= ranges::equal(y, z, {}, &Y::i, &Y::i); + ok &= ranges::equal(y, z, {}, &Y::j, &Y::j); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/replace_if/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/replace_if/constrained.cc new file mode 100644 index 00000000000..8ebcc411997 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/replace_if/constrained.cc @@ -0,0 +1,109 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + + friend constexpr bool + operator==(const X& a, const X& b) + { + return a.i == b.i; + } +}; + +void +test01() +{ + auto is_even_p = [] (int a) { return a%2 == 0; }; + auto is_negative_p = [] (int a) { return a < 0; }; + auto is_two_p = [] (int a) { return a == 2; }; + { + X x[6] = { {1}, {2}, {6}, {8}, {10}, {11} }; + X y[6] = { {1}, {9}, {9}, {9}, {9}, {11} }; + auto res = ranges::replace_if(x, x+5, is_even_p, X{9}, &X::i); + VERIFY( res == x+5 ); + VERIFY( ranges::equal(x, y) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + auto res = ranges::replace_if(x, x+5, is_negative_p, X{9}, &X::i); + VERIFY( res == x+5 ); + VERIFY( ranges::equal(x, y) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {10}, {11} }; + X y[6] = { {7}, {7}, {6}, {8}, {10}, {11} }; + test_container cx(x), cy(y); + auto res = ranges::replace_if(cx, is_two_p, X{7}, &X::i); + VERIFY( res == cx.end() ); + VERIFY( ranges::equal(cx, cy) ); + } + + { + int x[6] = { {2}, {2}, {6}, {8}, {10}, {2} }; + int y[6] = { {7}, {7}, {6}, {8}, {10}, {7} }; + test_range rx(x), ry(y); + auto res = ranges::replace_if(rx, is_two_p, 7); + VERIFY( res == rx.end() ); + + rx.bounds.first = x; + ry.bounds.first = y; + VERIFY( ranges::equal(rx, ry) ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + bool ok = true; + Y x[] = { {3,2}, {2,4}, {3,6} }; + Y y[] = { {4,5}, {2,4}, {4,5} }; + auto res = ranges::replace_if(x, [] (int a) { return a%2 == 1; }, + Y{4,5}, &Y::i); + ok &= res == x+3; + ok &= ranges::equal(x, y, {}, &Y::i, &Y::i); + ok &= ranges::equal(x, y, {}, &Y::j, &Y::j); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} + diff --git a/libstdc++-v3/testsuite/25_algorithms/reverse/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/reverse/constrained.cc new file mode 100644 index 00000000000..58cec27b5a0 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/reverse/constrained.cc @@ -0,0 +1,77 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_range; +using __gnu_test::test_container; +using __gnu_test::bidirectional_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +template typename wrapper> +void +test01() +{ + int x[] = { 1, 2, 3, 4 }; + test_container cx(x); + const int y[] = { 4, 3, 2, 1 }; + + auto res = ranges::reverse(cx); + VERIFY( res == ranges::end(cx) ); + VERIFY( ranges::equal(cx, y) ); +} + +template typename wrapper> +void +test02() +{ + int x[] = { 1, 2, 3, 4, 5 }; + test_range rx(x); + const int y[] = { 5, 4, 3, 2, 1 }; + + auto res = ranges::reverse(rx); + VERIFY( res == ranges::end(rx) ); + VERIFY( ranges::equal(rx, y) ); +} + +constexpr bool +test03() +{ + int x[] = { 1, 2, 3 }; + const int y[] = { 2, 1, 3 }; + ranges::reverse(x, x+2); + return ranges::equal(x, y); +} + +int +main() +{ + test01(); + test02(); + + test01(); + test02(); + + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/reverse_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/reverse_copy/constrained.cc new file mode 100644 index 00000000000..1ee40bedb39 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/reverse_copy/constrained.cc @@ -0,0 +1,74 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_range; +using __gnu_test::test_container; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = { 1, 2, 3, 4 }; + int w[4]; + test_container cx(x), cw(w); + const int y[] = { 4, 3, 2, 1 }; + + auto [in,out] = ranges::reverse_copy(cx, cw.begin()); + VERIFY( in == ranges::end(cx) && out == cw.end() ); + VERIFY( ranges::equal(cw, y) ); +} + +void +test02() +{ + int x[] = { 1, 2, 3, 4, 5 }; + int w[5]; + test_range rx(x), rw(w); + const int y[] = { 5, 4, 3, 2, 1 }; + + auto [in,out] = ranges::reverse_copy(rx, ranges::begin(rw)); + VERIFY( in == ranges::end(rx) && out == ranges::end(rw) ); + VERIFY( ranges::equal(rw, y) ); +} + +constexpr bool +test03() +{ + const int x[] = { 1, 2, 3 }; + int w[2]; + const int y[] = { 2, 1 }; + ranges::reverse_copy(x, x+2, w); + return ranges::equal(w, y); +} + +int +main() +{ + test01(); + test02(); + + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/rotate/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/rotate/constrained.cc new file mode 100644 index 00000000000..34095e743ad --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/rotate/constrained.cc @@ -0,0 +1,97 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + X (int a) : i(a) { } + + friend bool + operator==(const X& lhs, const X& rhs) + { + return lhs.i == rhs.i; + } +}; + +static_assert(!std::is_trivial_v); + +template typename> typename container, + template typename wrapper, + typename T = int> +void +test01() +{ + for (int a = 0; a <= 7; a++) + { + T x[] = {1, 2, 3, 4, 5, 6, 7}; + container rx(x); + auto i = ranges::begin(rx); + std::advance(i, a); + auto res = ranges::rotate(rx, i); + if (a == 0) + VERIFY( ranges::begin(res) == ranges::end(rx) ); + else + VERIFY( ranges::begin(res) + == std::next(ranges::begin(rx), + ranges::distance(i, ranges::end(rx))) ); + VERIFY( ranges::end(res) == ranges::end(rx) ); + for (int k = 0; k < 7; k++) + VERIFY( x[k] == (k+a)%7 + 1 ); + } +} + +constexpr bool +test02() +{ + int x[] = {1, 2, 3, 4}; + const int y[] = { 2, 3, 1, 4 }; + ranges::rotate(x, x+1, x+3); + return ranges::equal(x, y); +} + +int +main() +{ + test01(); + test01(); + + test01(); + test01(); + + test01(); + test01(); + + test01(); + test01(); + + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/rotate_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/rotate_copy/constrained.cc new file mode 100644 index 00000000000..f036377817b --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/rotate_copy/constrained.cc @@ -0,0 +1,93 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + X () : i(0) { } + X (int a) : i(a) { } + + friend bool + operator==(const X& lhs, const X& rhs) + { + return lhs.i == rhs.i; + } +}; + +static_assert(!std::is_trivial_v); + +template typename> typename container, + template typename wrapper, + typename T = int> +void +test01() +{ + for (int a = 0; a <= 7; a++) + { + T x[] = {1, 2, 3, 4, 5, 6, 7}; + T w[7]; + container rx(x), rw(w); + auto i = ranges::begin(rx); + std::advance(i, a); + auto [in,out] = ranges::rotate_copy(rx, i, ranges::begin(rw)); + VERIFY( in == ranges::end(rx) ); + VERIFY( out == ranges::end(rw) ); + for (int k = 0; k < 7; k++) + VERIFY( w[k] == (k+a)%7 + 1 ); + } +} + +constexpr bool +test02() +{ + const int x[] = {1, 2, 3, 4}; + int w[3]; + const int y[] = { 2, 3, 1}; + auto [in,out] = ranges::rotate_copy(x, x+1, x+3, w); + return (in == x+3 + && out == w+3 + && ranges::equal(w, y)); +} + +int +main() +{ + test01(); + test01(); + + test01(); + test01(); + + test01(); + test01(); + + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/search/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/search/constrained.cc new file mode 100644 index 00000000000..314d9d2acf0 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/search/constrained.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + X x[] = { {2}, {6}, {8}, {10}, {11} }; + X y[] = { {10}, {11} }; + { + + test_container c(x); + auto res = ranges::search(c, y, {}, &X::i, &X::i); + VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(c) ); + res = ranges::search(c, c, {}, &X::i, &X::i); + VERIFY( std::get<0>(res) == ranges::begin(c) + && std::get<1>(res) == ranges::end(c) ); + } + + { + test_range r(x); + auto res = ranges::search(r, y, {}, &X::i, &X::i); + VERIFY( std::get<0>(res)->i == 10 && std::get<1>(res) == ranges::end(r) ); + res = ranges::search(r, r, {}, &X::i, &X::i); + VERIFY( std::get<0>(res) == ranges::begin(r) + && std::get<1>(res) == ranges::end(r) ); + } +} + +void +test02() +{ + static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + static constexpr X y[] = { {6}, {8} }; + static constexpr int z[] = { 2, 8 }; + static constexpr int w[] = { 2 }; + + static_assert(std::get<0>(ranges::search(x, y, {}, &X::i, &X::i)) == x+2); + static_assert(std::get<1>(ranges::search(x, y, {}, &X::i, &X::i)) == x+4); + + static_assert(std::get<0>(ranges::search(x, z, {}, &X::i)) == x+6); + static_assert(std::get<1>(ranges::search(x, z, {}, &X::i)) == x+6); + + static_assert(std::get<0>(ranges::search(x, w, {}, &X::i)) == x+0); + static_assert(std::get<1>(ranges::search(x, w, {}, &X::i)) == x+1); + + static_assert(std::get<0>(ranges::search(x, x+6, w, w, {}, &X::i)) == x+0); + static_assert(std::get<1>(ranges::search(x, x+6, w, w, {}, &X::i)) == x+0); + + static_assert(std::get<0>(ranges::search(x, x, w, w+1, {}, &X::i)) == x+0); + static_assert(std::get<1>(ranges::search(x, x, w, w+1, {}, &X::i)) == x+0); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc new file mode 100644 index 00000000000..c1ac6da4bf8 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/search_n/constrained.cc @@ -0,0 +1,80 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + int x[] = { {2}, {2}, {6}, {8}, {10}, {11} }; + auto res = ranges::search_n(x+0, x+6, 2, 2); + VERIFY( res.begin() == x+0 && res.end() == x+2 ); + + int z[] = { {1}, {2}, {2}, {4}, {5}, {6} }; + res = ranges::search_n(z, 3, 3, std::greater()); + VERIFY( res.begin() == z+3 && res.end() == z+6 ); + + test_container cx(x); + auto res2 = ranges::search_n(cx, 2, 2); + VERIFY( res2.begin() == cx.begin() && *res2.end() == 6 ); + + int y[] = { {2}, {2}, {8}, {2}, {2}, {2}, {5} }; + test_range ry(y); + auto res3 = ranges::search_n(ry, 3, 2); + VERIFY( *res3.begin() == 2 && *res3.end() == 5 ); + + auto res4 = ranges::search_n(ry, 1, 8); + VERIFY( res4.begin().ptr == y+2 && res4.end().ptr == y+3 ); +} + +void +test02() +{ + static constexpr X x[] = { {2}, {2}, {6}, {8}, {10}, {2} }; + static constexpr X y[] = { {2}, {6}, {8}, {8}, {8}, {2} }; + static constexpr int z[] = { {2}, {6}, {8}, {10}, {2}, {2} }; + + static_assert(ranges::search_n(z, 0, 5).end() == z+0); + static_assert(ranges::search_n(z, 1, 5).begin() == z+6); + static_assert(ranges::search_n(x, 2, 3, {}, &X::i).begin() == x+6); + static_assert(ranges::search_n(x, 2, 2, {}, &X::i).end() == x+2); + static_assert(ranges::search_n(y, 3, 8, {}, &X::i).begin() == y+2); + static_assert(ranges::search_n(y, 3, 8, {}, &X::i).end() == y+5); +} + +int +main() +{ + test01(); + test02(); +} + diff --git a/libstdc++-v3/testsuite/25_algorithms/set_difference/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/set_difference/constrained.cc new file mode 100644 index 00000000000..3f46a9b523e --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/set_difference/constrained.cc @@ -0,0 +1,87 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {4,2,1,1,0}; + int y[] = {3,2,1}; + int z[3]; + test_range rx(x), ry(y); + test_range rz(z); + auto [in,out] + = ranges::set_difference(rx, ry, rz.begin(), ranges::greater{}); + VERIFY( in.ptr == x+5 ); + VERIFY( out.ptr == z+3 ); + VERIFY( ranges::equal(z, (int[]){4,1,0}) ); +} + +void +test02() +{ + int x[] = {3,2,1,1,0}; + int y[] = {3,2,2,1,0}; + int z[1]; + test_container rx(x), ry(y); + test_container rz(z); + auto [in,out] + = ranges::set_difference(rx.begin(), rx.end(), + ry.begin(), ry.end(), + rz.begin(), + {}, + std::negate<>{}, + std::negate<>{}); + VERIFY( in.ptr == x+5 ); + VERIFY( out.ptr == z+1 ); + VERIFY( ranges::equal(z, (int[]){1}) ); +} + +constexpr bool +test03() +{ + bool ok = true; + int x[1] = {0}; + int y[1] = {1}; + int z[1]; + ok &= ranges::set_difference(x, x, y, y+1, z).out == z; + ok &= ranges::set_difference(x, x+1, y, y, z).out == z+1; + ok &= z[0] == 0; + return ok; +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/set_intersection/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/set_intersection/constrained.cc new file mode 100644 index 00000000000..0db3e411871 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/set_intersection/constrained.cc @@ -0,0 +1,88 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {4,2,1,1,0}; + int y[] = {3,2,1}; + int z[2]; + test_range rx(x), ry(y); + test_range rz(z); + auto [in1,in2,out] + = ranges::set_intersection(rx, ry, rz.begin(), ranges::greater{}); + VERIFY( in1.ptr == x+5 ); + VERIFY( in2.ptr == y+3 ); + VERIFY( out.ptr == z+2 ); + VERIFY( ranges::equal(z, (int[]){2,1}) ); +} + +void +test02() +{ + int x[] = {3,2,1,1,0}; + int y[] = {3,2,1,0}; + int z[4]; + test_container rx(x), ry(y); + test_container rz(z); + auto [in1,in2,out] + = ranges::set_intersection(rx.begin(), rx.end(), + ry.begin(), ry.end(), + rz.begin(), + {}, + std::negate<>{}, + std::negate<>{}); + VERIFY( in1.ptr == x+5 ); + VERIFY( in2.ptr == y+4 ); + VERIFY( out.ptr == z+4 ); + VERIFY( ranges::equal(z, (int[]){3,2,1,0}) ); +} + +constexpr bool +test03() +{ + bool ok = true; + int x[1] = {0}; + int y[1] = {1}; + int z[1]; + ok &= ranges::set_intersection(x, x, y, y+1, z).out == z; + ok &= ranges::set_intersection(x, x+1, y, y, z).out == z; + return ok; +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/set_symmetric_difference/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/set_symmetric_difference/constrained.cc new file mode 100644 index 00000000000..b138aee3adb --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/set_symmetric_difference/constrained.cc @@ -0,0 +1,123 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {4,2,1,1,0}; + int y[] = {3,2,2,1}; + int z[5]; + test_range rx(x), ry(y); + test_range rz(z); + auto [in1,in2,out] + = ranges::set_symmetric_difference(rx, ry, rz.begin(), ranges::greater{}); + VERIFY( in1.ptr == x+5 ); + VERIFY( in2.ptr == y+4 ); + VERIFY( out.ptr == z+5 ); + VERIFY( ranges::equal(z, (int[]){4,3,2,1,0}) ); +} + +void +test02() +{ + int x[] = {3,2,1,1,0}; + int y[] = {3,2,1,0}; + int z[1]; + test_container rx(x), ry(y); + test_container rz(z); + auto [in1,in2,out] + = ranges::set_symmetric_difference(rx.begin(), rx.end(), + ry.begin(), ry.end(), + rz.begin(), + {}, + std::negate<>{}, + std::negate<>{}); + VERIFY( in1.ptr == x+5 ); + VERIFY( in2.ptr == y+4 ); + VERIFY( out.ptr == z+1 ); + VERIFY( ranges::equal(z, (int[]){1}) ); +} + +constexpr bool +test03() +{ + bool ok = true; + int x[1] = {0}; + int y[1] = {1}; + int z[1]; + ok &= ranges::set_symmetric_difference(x, x, y, y+1, z).out == z+1; + ok &= z[0] == 1; + ok &= ranges::set_symmetric_difference(x, x+1, y, y, z).out == z+1; + ok &= z[0] == 0; + return ok; +} + +void +test04() +{ + int x[15] = {5,5,5,5,5,4,4,4,4,3,3,3,2,2,1}; + int y[15] = {5,5,5,5,5,4,4,4,4,3,3,3,2,2,1}; + for (int k = 0; k < 100; k++) + { + std::ranlux48_base g(k); + ranges::shuffle(x, g); + ranges::shuffle(y, g); + ranges::sort(x, x+10); + ranges::sort(y, y+10); + + int z[15]; + auto z_out = ranges::set_symmetric_difference(x, x+10, y, y+10, z).out; + + int w1[15]; + auto w1_out = ranges::set_difference(x, x+10, y, y+10, w1).out; + + int w2[15]; + auto w2_out = ranges::set_difference(y, y+10, x, x+10, w2).out; + + int w3[15]; + auto w3_out = ranges::set_union(w1, w1_out, w2, w2_out, w3).out; + + VERIFY( ranges::equal(z, z_out, w3, w3_out) ); + } +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); + test04(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/set_union/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/set_union/constrained.cc new file mode 100644 index 00000000000..19bcd7aab9f --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/set_union/constrained.cc @@ -0,0 +1,91 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {4,2,1,1,0}; + int y[] = {3,2,1}; + int z[6]; + test_range rx(x), ry(y); + test_range rz(z); + auto [in1,in2,out] + = ranges::set_union(rx, ry, rz.begin(), + ranges::greater{}); + VERIFY( in1.ptr == x+5 ); + VERIFY( in2.ptr == y+3 ); + VERIFY( out.ptr == z+6 ); + VERIFY( ranges::equal(z, (int[]){4,3,2,1,1,0}) ); +} + +void +test02() +{ + int x[] = {4,2,1,1,0}; + int y[] = {3,2,1,1,0}; + int z[6]; + test_container rx(x), ry(y); + test_container rz(z); + auto [in1,in2,out] + = ranges::set_union(rx.begin(), rx.end(), + ry.begin(), ry.end(), + rz.begin(), + {}, + std::negate<>{}, + std::negate<>{}); + VERIFY( in1.ptr == x+5 ); + VERIFY( in2.ptr == y+5 ); + VERIFY( out.ptr == z+6 ); + VERIFY( ranges::equal(z, (int[]){4,3,2,1,1,0}) ); +} + +constexpr bool +test03() +{ + bool ok = true; + int x[1] = {0}; + int y[1] = {1}; + int z[1]; + ranges::set_union(x, x, y, y+1, z); + ok &= z[0] == 1; + ranges::set_union(x, x+1, y, y, z); + ok &= z[0] == 0; + return ok; +} + +int +main() +{ + test01(); + test02(); + static_assert(test03()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/shuffle/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/shuffle/constrained.cc new file mode 100644 index 00000000000..b96343aecce --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/shuffle/constrained.cc @@ -0,0 +1,70 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +// This test is adapted from 25_algorithms/shuffle/1.cc. + +void +test01() +{ + for (unsigned size = 0; size < 50; ++size) + { + std::vector vref(size); + std::iota(vref.begin(), vref.end(), 0); + std::vector v1(vref), v2(vref); + test_container c + = {&v1[0], &v1[0] + size}; + test_range r + = {&v2[0], &v2[0] + size}; + + std::ranlux48_base g1(size), g2(size + 1); + VERIFY( ranges::shuffle(c, g1) == c.end() ); + VERIFY( ranges::shuffle(ranges::begin(r), ranges::end(r), g2) + == ranges::end(r) ); + + if (size >= 10) + { + VERIFY( !ranges::equal(c, vref) ); + VERIFY( !ranges::equal(r, vref) ); + VERIFY( !ranges::equal(c, r) ); + } + + VERIFY( ranges::is_permutation(c, vref) ); + VERIFY( ranges::is_permutation(r, vref) ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/sort/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/sort/constrained.cc new file mode 100644 index 00000000000..d8227773ccb --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/sort/constrained.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + for (unsigned size = 0; size < 50; ++size) + { + std::vector vref(size); + std::iota(vref.begin(), vref.end(), 0); + std::vector v1(vref), v2(vref); + test_container c + = {&v1[0], &v1[0] + size}; + test_range r + = {&v2[0], &v2[0] + size}; + + std::ranlux48_base g1(size), g2(size + 1); + ranges::shuffle(c, g1); + ranges::shuffle(ranges::begin(r), ranges::end(r), g2); + + VERIFY( ranges::sort(c) == c.end() ); + VERIFY( ranges::sort(r) == ranges::end(r) ); + + VERIFY( ranges::equal(c, vref) ); + VERIFY( ranges::equal(r, vref) ); + } +} + +struct X +{ + int i; + constexpr X(int a) : i(a) { } +}; + +constexpr bool +test02() +{ + X x[] = {3,4,2,1,5}; + const X y[] = {4,3,2,1,5}; + + auto res = ranges::sort(x, x+4, ranges::greater{}, &X::i); + return (res == x+4 + && ranges::equal(x, y, {}, &X::i, &X::i)); +} + +int +main() +{ + test01(); + static_assert(test02()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_partition/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/stable_partition/constrained.cc new file mode 100644 index 00000000000..761e3dd32d4 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_partition/constrained.cc @@ -0,0 +1,76 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + { + int x[] = {1,2,3,4,5,6,7,8,9,10}; + test_container cx(x); + auto pred = [] (int a) { return a%2==0; }; + auto range = ranges::stable_partition(cx, pred); + VERIFY( ranges::all_of(cx.begin(), range.begin(), pred) ); + VERIFY( ranges::none_of(range, pred) ); + } + + { + int x[] = {1,2,3,4,5,6,7,8,9,10,11}; + test_range cx(x); + auto pred = [] (int a) { return a%2==0; }; + auto range = ranges::stable_partition(cx, pred); + VERIFY( ranges::all_of(cx.begin(), range.begin(), pred) ); + VERIFY( ranges::none_of(range, pred) ); + } +} + +void +test02() +{ + for (int k = 1; k <= 10; k++) + { + int x[] = {1,2,3,4,5,6,7,8,9,10}; + auto pred = [&] (int a) { return a >= k; }; + auto proj = [] (int a) { return a-1; }; + auto range = ranges::stable_partition(x, x+10, pred, proj); + VERIFY( ranges::all_of(x, range.begin(), pred, proj) ); + VERIFY( ranges::none_of(range, pred, proj) ); + + int y[] = {0,1,2,3,4,5,6,7,8,9}; + ranges::rotate(y, y+k); + VERIFY( ranges::equal(x, y, {}, proj) ); + } +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/stable_sort/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/stable_sort/constrained.cc new file mode 100644 index 00000000000..23a8c03b519 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/stable_sort/constrained.cc @@ -0,0 +1,70 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } +// { dg-require-cstdint "" } + +#include +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::random_access_iterator_wrapper; + +namespace ranges = std::ranges; + +// This test doesn't verify the stability property of ranges::stable_sort, +// because at the moment it's just defined to be a wrapper over +// std::stable_sort. + +void +test01() +{ + for (unsigned size = 0; size < 50; ++size) + { + std::vector vref(size); + std::iota(vref.begin(), vref.end(), 0); + std::vector v1(vref), v2(vref); + test_container c + = {&v1[0], &v1[0] + size}; + test_range r + = {&v2[0], &v2[0] + size}; + + std::ranlux48_base g1(size), g2(size + 1); + ranges::shuffle(c, g1); + ranges::shuffle(ranges::begin(r), ranges::end(r), g2); + + auto res1 = ranges::stable_sort(c.begin(), c.end(), {}, std::negate<>{}); + VERIFY( res1 == c.end() ); + + auto res2 = ranges::stable_sort(r, ranges::greater{}); + VERIFY( res2 == ranges::end(r) ); + + VERIFY( ranges::equal(c, r) ); + VERIFY( ranges::equal(c.begin(), c.end(), vref.rbegin(), vref.rend()) ); + } +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/swap_ranges/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/constrained.cc new file mode 100644 index 00000000000..338b6a435f9 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/swap_ranges/constrained.cc @@ -0,0 +1,124 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; +using __gnu_test::bidirectional_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X +{ + int i; + int moved = 0; + + constexpr X(int a) : i(a) { } + + constexpr X(const X&) = delete; + constexpr X& operator=(const X&) = delete; + + constexpr X(X&& other) + { + *this = std::move(other); + } + + constexpr X& + operator=(X&& other) + { + other.moved++; + i = other.i; + return *this; + } + + friend constexpr bool + operator==(const X& a, const X& b) + { return a.i == b.i; } +}; + +void +test01() +{ + { + X x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + X y[7] = { 2, 4, 3, 5, 8, 9, 1 }; + X z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + X w[7] = { 2, 4, 3, 5, 8, 9, 1 }; + auto [x_iter, y_iter] = ranges::swap_ranges(x, y); + VERIFY( ranges::equal(y, z) && x_iter == x+7 && y_iter == y+7 ); + VERIFY( ranges::equal(x, w) ); + } + + { + int x[3] = { 1, 2, 3 }; + int y[4] = { 2, 4, 6, 0 }; + int z[3] = { 1, 2, 3 }; + int w[3] = { 2, 4, 6 }; + test_container cx(x); + test_container cy(y); + auto [x_iter, y_iter] = ranges::swap_ranges(cx, cy); + VERIFY( ranges::equal(y, y+3, z, z+3) ); + VERIFY( x_iter.ptr == x+3 && y_iter.ptr == y+3 ); + VERIFY( y[3] == 0 ); + VERIFY( ranges::equal(x, w) ); + } + + { + int x[3] = { 1, 2, 3 }; + int y[4] = { 2, 4, 6, 0 }; + int z[3] = { 1, 2, 3 }; + int w[3] = { 2, 4, 6 }; + test_range cx(x); + test_range cy(y); + auto [y_iter, x_iter] = ranges::swap_ranges(cy, cx); + VERIFY( ranges::equal(y, y+3, z, z+3) ); + VERIFY( x_iter.ptr == x+3 && y_iter.ptr == y+3 ); + VERIFY( y[3] == 0 ); + VERIFY( ranges::equal(x, w) ); + } +} + +constexpr bool +test02() +{ + bool ok = true; + X x[7] = { 1, 2, 3, 4, 5, 6, 7 }; + X y[7] = { 2, 4, 3, 5, 8, 9, 1 }; + X z[7] = { 1, 2, 3, 4, 5, 6, 7 }; + X w[7] = { 2, 4, 3, 5, 8, 9, 1 }; + auto [x_iter, y_iter] = ranges::swap_ranges(x, y); + ok &= ranges::equal(y, z) && x_iter == x+7 && y_iter == y+7; + ok &= ranges::equal(x, w); + return ok; +} + +int +main() +{ + test01(); + static_assert(test02()); +} + + diff --git a/libstdc++-v3/testsuite/25_algorithms/transform/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/transform/constrained.cc new file mode 100644 index 00000000000..da8b7f2be07 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/transform/constrained.cc @@ -0,0 +1,148 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +struct X { int i; }; + +void +test01() +{ + { + int x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + int y[6] = { {3}, {5}, {7}, {9}, {11}, {12} }; + auto [in, out] = ranges::transform(x, x, [] (int a) { return a+1; }); + VERIFY( in == x+6 && out == x+6 ); + VERIFY( ranges::equal(x, y) ); + } + + { + X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + int y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} }; + int z[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} }; + test_container cx(x); + test_container cy(y), cz(z); + auto [in, out] + = ranges::transform(cx, cz.begin(), [] (int a) { return a+1; }, &X::i); + VERIFY( ranges::equal(cy, cz) ); + VERIFY( in == cx.end() && ++out == cz.end() ); + } + + { + X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + X y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} }; + int z[7] = { {0}, {0}, {0}, {0}, {0}, {0}, {0} }; + test_range rx(x), ry(y); + test_range rz(z); + auto [in, out] + = ranges::transform(rx, rz.begin(), [] (int a) { return a+1; }, &X::i); + VERIFY( ranges::equal(ry, z, {}, &X::i) ); + VERIFY( in == rx.end() && out.ptr == z+6 ); + } +} + +struct Y { int i; int j; }; + +constexpr bool +test02() +{ + int x[] = { 1, 2, 3 }; + Y y[] = { {1,2}, {2,4}, {3,6} }; + ranges::transform(y, y+3, x, [] (int a) { return -a; }, &Y::i); + return x[0] == -1 && x[1] == -2 && x[2] == -3; +} + +void +test03() +{ + { + int x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + const int y[6] = { {3}, {5}, {7}, {9}, {11}, {12} }; + int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} }; + auto [in1, in2, out] = ranges::transform(x, y, x, std::plus<>{}); + VERIFY( in1 == x+6 && in2 == y+6 && out == x+6 ); + VERIFY( ranges::equal(x, z) ); + } + + { + int x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + const int y[6] = { {3}, {5}, {7}, {9}, {11}, {12} }; + int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} }; + auto [in1, in2, out] = ranges::transform(y, x, x, std::plus<>{}); + VERIFY( in1 == y+6 && in2 == x+6 && out == x+6 ); + VERIFY( ranges::equal(x, z) ); + } + + { + X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + int y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} }; + int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} }; + int w[6]; + test_container cx(x); + test_container cy(y), cz(z), cw(w); + auto [in1, in2, out] + = ranges::transform(cx, cy, cw.begin(), std::plus<>{}, &X::i); + VERIFY( in1 == cx.end() && ++in2 == cy.end() && out == cw.end() ); + VERIFY( ranges::equal(cw, cz) ); + } + + { + X x[6] = { {2}, {4}, {6}, {8}, {10}, {11} }; + int y[7] = { {3}, {5}, {7}, {9}, {11}, {12}, {0} }; + int z[6] = { {5}, {9}, {13}, {17}, {21}, {23} }; + int w[6]; + test_range rx(x); + test_range ry(y), rz(z); + test_range rw(w); + auto [in1, in2, out] + = ranges::transform(rx, ry, rw.begin(), std::plus<>{}, &X::i); + VERIFY( in1 == rx.end() && ++in2 == ry.end() && out.ptr == w+6 ); + VERIFY( ranges::equal(w, rz) ); + } +} + +constexpr bool +test04() +{ + int x[3]; + const Y y[3] = { {1,2}, {2,4}, {3,6} }; + ranges::transform(y, y+3, y, y+3, x, std::plus<>{}, &Y::i, &Y::j); + return x[0] == 3 && x[1] == 6 && x[2] == 9; +} + +int +main() +{ + test01(); + static_assert(test02()); + test03(); + static_assert(test04()); +} + diff --git a/libstdc++-v3/testsuite/25_algorithms/unique/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/unique/constrained.cc new file mode 100644 index 00000000000..e863a601ddd --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/unique/constrained.cc @@ -0,0 +1,143 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + + +namespace ranges = std::ranges; + +struct X +{ + int i; +}; + +void +test01() +{ + { + X x[6] = { {2}, {2}, {6}, {8}, {2}, {11} }; + const int y[5] = { {2}, {6}, {8}, {2}, {11} }; + test_container cx(x); + auto res = ranges::unique(cx, {}, &X::i); + VERIFY( res.end() == cx.end() ); + VERIFY( ranges::equal(cx.begin(), res.begin(), y, y+5, {}, &X::i) ); + } + + { + X x[6] = { {2}, {2}, {6}, {8}, {2}, {11} }; + const int y[5] = { {2}, {6}, {8}, {2}, {11} }; + test_range rx(x); + auto res = ranges::unique(rx, {}, &X::i); + VERIFY( res.end() == rx.end() ); + VERIFY( ranges::equal(rx.begin(), res.begin(), y, y+5, {}, &X::i) ); + } +} + +constexpr bool +test02() +{ + int x[2] = {2, 2}; + const int y[1] = {2}; + auto res = ranges::unique(x); + return ranges::equal(x, res.begin(), y, y+1, ranges::equal_to{}); +} + +/* The following is adapted from 25_algorithms/unique/2.cc. */ + +namespace two_dot_cc +{ + const int T1[] = {1, 4, 4, 6, 1, 2, 2, 3, 1, 6, 6, 6, 5, 7, 5, 4, 4}; + const int T2[] = {1, 1, 1, 2, 2, 1, 1, 7, 6, 6, 7, 8, 8, 8, 8, 9, 9}; + const int N = sizeof(T1) / sizeof(int); + + const int A1[] = {1, 4, 6, 1, 2, 3, 1, 6, 5, 7, 5, 4}; + const int A2[] = {1, 4, 4, 6, 6, 6, 6, 7}; + const int A3[] = {1, 1, 1}; + + const int B1[] = {1, 2, 1, 7, 6, 7, 8, 9}; + const int B2[] = {1, 1, 1, 2, 2, 7, 7, 8, 8, 8, 8, 9, 9}; + const int B3[] = {9, 9, 8, 8, 8, 8, 7, 6, 6, 1, 1, 1, 1, 1}; + + void test01() + { + using namespace std; + + list::iterator pos; + + list coll(T1, T1 + N); + pos = ranges::unique(coll.begin(), coll.end()).begin(); + VERIFY( equal(coll.begin(), pos, A1) ); + + list coll2(T2, T2 + N); + pos = ranges::unique(coll2.begin(), coll2.end()).begin(); + VERIFY( equal(coll2.begin(), pos, B1) ); + } + + void test02() + { + using namespace std; + + list::iterator pos; + + list coll(T1, T1 + N); + pos = ranges::unique(coll.begin(), coll.end(), greater()).begin(); + VERIFY( equal(coll.begin(), pos, A2) ); + + list coll2(T2, T2 + N); + pos = ranges::unique(coll2.begin(), coll2.end(), greater()).begin(); + VERIFY( equal(coll2.begin(), pos, B2) ); + } + + void test03() + { + using namespace std; + + list::iterator pos; + + list coll(T1, T1 + N); + pos = ranges::unique(coll.begin(), coll.end(), less()).begin(); + VERIFY( equal(coll.begin(), pos, A3) ); + + list coll2(T2, T2 + N); + reverse(coll2.begin(), coll2.end()); + pos = ranges::unique(coll2.begin(), coll2.end(), less()).begin(); + VERIFY( equal(coll2.begin(), pos, B3) ); + } +} // namespace two_dot_cc + +int main() +{ + test01(); + static_assert(test02()); + + two_dot_cc::test01(); + two_dot_cc::test02(); + two_dot_cc::test03(); + + return 0; +} diff --git a/libstdc++-v3/testsuite/25_algorithms/unique_copy/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/unique_copy/constrained.cc new file mode 100644 index 00000000000..bf16cdc4ee9 --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/unique_copy/constrained.cc @@ -0,0 +1,113 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_range; +using __gnu_test::input_iterator_wrapper; +using __gnu_test::output_iterator_wrapper; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +template typename source_wrapper, + template typename dest_wrapper> +void +test01() +{ + int x[6] = {0, 0, 0, 1, 1, 1}; + int y[2]; + const int z[2] = {0, 1}; + + test_range rx(x); + test_range ry(y); + auto [in,out] = ranges::unique_copy(rx, ry.begin()); + VERIFY( in == ranges::end(rx) && out == ranges::end(ry) ); + VERIFY( ranges::equal(y, z) ); +} + +template typename source_wrapper, + template typename dest_wrapper> +void +test02() +{ + int x[6] = {0, 0, 0, 1, 1, 1}; + int y[2] = {0, 0}; + const int z[2] = {0, 0}; + + test_range rx(x, x); + test_range ry(y, y); + auto [in, out] = ranges::unique_copy(rx.begin(), rx.end(), ry.begin()); + VERIFY( in.ptr == x && out.ptr == y ); + VERIFY( ranges::equal(y, z) ); +} + +template typename source_wrapper, + template typename dest_wrapper> +void +test03() +{ + struct X { int i; }; + X x[6] = { {1}, {2}, {2}, {4}, {4}, {6} }; + X y[4] = { {1}, {2}, {4}, {6} }; + const X z[4] = { {1}, {2}, {4}, {6} }; + + test_range rx(x); + test_range ry(y); + auto [in, out] + = ranges::unique_copy(rx, ry.begin(), ranges::equal_to{}, &X::i); + VERIFY( in == ranges::end(rx) && out == ranges::end(ry) ); + VERIFY( ranges::equal(y, z, {}, &X::i, &X::i) ); +} + +constexpr bool +test04() +{ + struct X { int i; }; + X x[7] = { {1}, {2}, {2}, {2}, {4}, {4}, {6} }; + X y[4] = { {1}, {2}, {4}, {6} }; + const X z[4] = { {1}, {2}, {4}, {6} }; + + auto [in, out] + = ranges::unique_copy(x, x+7, y, ranges::equal_to{}, &X::i); + return (in == ranges::end(x) + && out == ranges::end(y) + && ranges::equal(y, z, {}, &X::i, &X::i)); +} + +int +main() +{ + test01(); + test01(); + test01(); + + test02(); + test02(); + test02(); + + test03(); + test03(); + test03(); + + static_assert(test04()); +} diff --git a/libstdc++-v3/testsuite/25_algorithms/upper_bound/constrained.cc b/libstdc++-v3/testsuite/25_algorithms/upper_bound/constrained.cc new file mode 100644 index 00000000000..5182431f68f --- /dev/null +++ b/libstdc++-v3/testsuite/25_algorithms/upper_bound/constrained.cc @@ -0,0 +1,66 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include +#include +#include + +using __gnu_test::test_container; +using __gnu_test::test_range; +using __gnu_test::forward_iterator_wrapper; + +namespace ranges = std::ranges; + +void +test01() +{ + int x[] = {1, 2, 3, 4, 5, 5, 6, 7}; + for (unsigned i = 0; i < 5; i++) + for (unsigned j = 6; j < 8; j++) + { + test_container cx(x); + auto result = ranges::upper_bound(std::next(cx.begin(), i), + std::next(cx.begin(), j), + 4, {}, [] (int a) { return a-1; }); + VERIFY( result.ptr == x+6 ); + } + + ranges::reverse(x); + test_range rx(x); + auto result = ranges::upper_bound(rx, 5, ranges::greater{}, + [] (int a) { return a+1; }); + VERIFY( result.ptr == x+5 ); +} + +constexpr bool +test02() +{ + int x[] = {1, 2, 3, 4, 5}; + return (ranges::upper_bound(x, 6) == x+5 + && ranges::upper_bound(x, x, 6) == x + && ranges::upper_bound(x, 1) == x+1); +} + +int +main() +{ + test01(); + static_assert(test02()); +}