1134723edSLouis Dionne //===----------------------------------------------------------------------===//
2134723edSLouis Dionne //
3134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6134723edSLouis Dionne //
7134723edSLouis Dionne //===----------------------------------------------------------------------===//
8134723edSLouis Dionne
9134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_UNIQUE_COPY_H
10134723edSLouis Dionne #define _LIBCPP___ALGORITHM_UNIQUE_COPY_H
11134723edSLouis Dionne
12134723edSLouis Dionne #include <__algorithm/comp.h>
1372f57e3aSHui Xie #include <__algorithm/iterator_operations.h>
144d81a46fSArthur O'Dwyer #include <__config>
15134723edSLouis Dionne #include <__iterator/iterator_traits.h>
1672f57e3aSHui Xie #include <__type_traits/conditional.h>
1772f57e3aSHui Xie #include <__type_traits/is_base_of.h>
1872f57e3aSHui Xie #include <__type_traits/is_same.h>
1972f57e3aSHui Xie #include <__utility/move.h>
2072f57e3aSHui Xie #include <__utility/pair.h>
21134723edSLouis Dionne
22134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
23134723edSLouis Dionne # pragma GCC system_header
24134723edSLouis Dionne #endif
25134723edSLouis Dionne
26*7b462251SLouis Dionne _LIBCPP_PUSH_MACROS
27*7b462251SLouis Dionne #include <__undef_macros>
28*7b462251SLouis Dionne
29134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD
30134723edSLouis Dionne
3172f57e3aSHui Xie namespace __unique_copy_tags {
3272f57e3aSHui Xie
3372f57e3aSHui Xie struct __reread_from_input_tag {};
3472f57e3aSHui Xie struct __reread_from_output_tag {};
3572f57e3aSHui Xie struct __read_from_tmp_value_tag {};
3672f57e3aSHui Xie
3772f57e3aSHui Xie } // namespace __unique_copy_tags
3872f57e3aSHui Xie
3972f57e3aSHui Xie template <class _AlgPolicy, class _BinaryPredicate, class _InputIterator, class _Sent, class _OutputIterator>
405146b57bSNikolas Klauser _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _OutputIterator>
__unique_copy(_InputIterator __first,_Sent __last,_OutputIterator __result,_BinaryPredicate && __pred,__unique_copy_tags::__read_from_tmp_value_tag)4172f57e3aSHui Xie __unique_copy(_InputIterator __first,
4272f57e3aSHui Xie _Sent __last,
4372f57e3aSHui Xie _OutputIterator __result,
4472f57e3aSHui Xie _BinaryPredicate&& __pred,
4572f57e3aSHui Xie __unique_copy_tags::__read_from_tmp_value_tag) {
4672f57e3aSHui Xie if (__first != __last) {
4772f57e3aSHui Xie typename _IterOps<_AlgPolicy>::template __value_type<_InputIterator> __t(*__first);
48134723edSLouis Dionne *__result = __t;
49134723edSLouis Dionne ++__result;
5072f57e3aSHui Xie while (++__first != __last) {
5172f57e3aSHui Xie if (!__pred(__t, *__first)) {
52134723edSLouis Dionne __t = *__first;
53134723edSLouis Dionne *__result = __t;
54134723edSLouis Dionne ++__result;
55134723edSLouis Dionne }
56134723edSLouis Dionne }
57134723edSLouis Dionne }
5872f57e3aSHui Xie return pair<_InputIterator, _OutputIterator>(std::move(__first), std::move(__result));
59134723edSLouis Dionne }
60134723edSLouis Dionne
6172f57e3aSHui Xie template <class _AlgPolicy, class _BinaryPredicate, class _ForwardIterator, class _Sent, class _OutputIterator>
625146b57bSNikolas Klauser _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_ForwardIterator, _OutputIterator>
__unique_copy(_ForwardIterator __first,_Sent __last,_OutputIterator __result,_BinaryPredicate && __pred,__unique_copy_tags::__reread_from_input_tag)6372f57e3aSHui Xie __unique_copy(_ForwardIterator __first,
6472f57e3aSHui Xie _Sent __last,
6572f57e3aSHui Xie _OutputIterator __result,
6672f57e3aSHui Xie _BinaryPredicate&& __pred,
6772f57e3aSHui Xie __unique_copy_tags::__reread_from_input_tag) {
6872f57e3aSHui Xie if (__first != __last) {
69134723edSLouis Dionne _ForwardIterator __i = __first;
70134723edSLouis Dionne *__result = *__i;
71134723edSLouis Dionne ++__result;
7272f57e3aSHui Xie while (++__first != __last) {
7372f57e3aSHui Xie if (!__pred(*__i, *__first)) {
74134723edSLouis Dionne *__result = *__first;
75134723edSLouis Dionne ++__result;
76134723edSLouis Dionne __i = __first;
77134723edSLouis Dionne }
78134723edSLouis Dionne }
79134723edSLouis Dionne }
8072f57e3aSHui Xie return pair<_ForwardIterator, _OutputIterator>(std::move(__first), std::move(__result));
81134723edSLouis Dionne }
82134723edSLouis Dionne
8372f57e3aSHui Xie template <class _AlgPolicy, class _BinaryPredicate, class _InputIterator, class _Sent, class _InputAndOutputIterator>
845146b57bSNikolas Klauser _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI pair<_InputIterator, _InputAndOutputIterator>
__unique_copy(_InputIterator __first,_Sent __last,_InputAndOutputIterator __result,_BinaryPredicate && __pred,__unique_copy_tags::__reread_from_output_tag)8572f57e3aSHui Xie __unique_copy(_InputIterator __first,
8672f57e3aSHui Xie _Sent __last,
8772f57e3aSHui Xie _InputAndOutputIterator __result,
8872f57e3aSHui Xie _BinaryPredicate&& __pred,
8972f57e3aSHui Xie __unique_copy_tags::__reread_from_output_tag) {
9072f57e3aSHui Xie if (__first != __last) {
91134723edSLouis Dionne *__result = *__first;
92134723edSLouis Dionne while (++__first != __last)
93134723edSLouis Dionne if (!__pred(*__result, *__first))
94134723edSLouis Dionne *++__result = *__first;
95134723edSLouis Dionne ++__result;
96134723edSLouis Dionne }
9772f57e3aSHui Xie return pair<_InputIterator, _InputAndOutputIterator>(std::move(__first), std::move(__result));
98134723edSLouis Dionne }
99134723edSLouis Dionne
100134723edSLouis Dionne template <class _InputIterator, class _OutputIterator, class _BinaryPredicate>
1015146b57bSNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
unique_copy(_InputIterator __first,_InputIterator __last,_OutputIterator __result,_BinaryPredicate __pred)10272f57e3aSHui Xie unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _BinaryPredicate __pred) {
103ed2d3644SNikolas Klauser using __algo_tag = __conditional_t<
10472f57e3aSHui Xie is_base_of<forward_iterator_tag, typename iterator_traits<_InputIterator>::iterator_category>::value,
10572f57e3aSHui Xie __unique_copy_tags::__reread_from_input_tag,
106ed2d3644SNikolas Klauser __conditional_t<
10772f57e3aSHui Xie is_base_of<forward_iterator_tag, typename iterator_traits<_OutputIterator>::iterator_category>::value &&
10872f57e3aSHui Xie is_same< typename iterator_traits<_InputIterator>::value_type,
10972f57e3aSHui Xie typename iterator_traits<_OutputIterator>::value_type>::value,
11072f57e3aSHui Xie __unique_copy_tags::__reread_from_output_tag,
111ed2d3644SNikolas Klauser __unique_copy_tags::__read_from_tmp_value_tag> >;
11272f57e3aSHui Xie return std::__unique_copy<_ClassicAlgPolicy>(
11372f57e3aSHui Xie std::move(__first), std::move(__last), std::move(__result), __pred, __algo_tag())
11472f57e3aSHui Xie .second;
115134723edSLouis Dionne }
116134723edSLouis Dionne
117134723edSLouis Dionne template <class _InputIterator, class _OutputIterator>
1185146b57bSNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _OutputIterator
unique_copy(_InputIterator __first,_InputIterator __last,_OutputIterator __result)11972f57e3aSHui Xie unique_copy(_InputIterator __first, _InputIterator __last, _OutputIterator __result) {
120e07ca2aeSAlvin Wong return std::unique_copy(std::move(__first), std::move(__last), std::move(__result), __equal_to());
121134723edSLouis Dionne }
122134723edSLouis Dionne
123134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD
124134723edSLouis Dionne
125*7b462251SLouis Dionne _LIBCPP_POP_MACROS
126*7b462251SLouis Dionne
127134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_UNIQUE_COPY_H
128