185587Sobrien//===----------------------------------------------------------------------===//
285587Sobrien//
385587Sobrien// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
485587Sobrien// See https://llvm.org/LICENSE.txt for license information.
585587Sobrien// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
685587Sobrien//
785587Sobrien//===----------------------------------------------------------------------===//
885587Sobrien
985587Sobrien#ifndef _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H
1085587Sobrien#define _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H
1185587Sobrien
1285587Sobrien#include <__algorithm/in_in_out_result.h>
1385587Sobrien#include <__algorithm/iterator_operations.h>
1485587Sobrien#include <__algorithm/make_projected.h>
1585587Sobrien#include <__algorithm/set_symmetric_difference.h>
1685587Sobrien#include <__config>
1785587Sobrien#include <__functional/identity.h>
1885587Sobrien#include <__functional/invoke.h>
1985587Sobrien#include <__functional/ranges_operations.h>
2085587Sobrien#include <__iterator/concepts.h>
2185587Sobrien#include <__iterator/mergeable.h>
2285587Sobrien#include <__ranges/access.h>
2385587Sobrien#include <__ranges/concepts.h>
2485587Sobrien#include <__ranges/dangling.h>
2585587Sobrien#include <__utility/move.h>
2685587Sobrien
2785587Sobrien#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
2885587Sobrien#  pragma GCC system_header
2985587Sobrien#endif
3085587Sobrien
3185587Sobrien_LIBCPP_PUSH_MACROS
3285587Sobrien#include <__undef_macros>
3385587Sobrien
3485587Sobrien#if _LIBCPP_STD_VER >= 20
3585587Sobrien
3685587Sobrien_LIBCPP_BEGIN_NAMESPACE_STD
3785587Sobrien
3885587Sobriennamespace ranges {
3985587Sobrien
4085587Sobrientemplate <class _InIter1, class _InIter2, class _OutIter>
4185587Sobrienusing set_symmetric_difference_result = in_in_out_result<_InIter1, _InIter2, _OutIter>;
4285587Sobrien
4385587Sobriennamespace __set_symmetric_difference {
4485587Sobrien
4585587Sobrienstruct __fn {
4685587Sobrien  template <input_iterator _InIter1,
4785587Sobrien            sentinel_for<_InIter1> _Sent1,
4885587Sobrien            input_iterator _InIter2,
4985587Sobrien            sentinel_for<_InIter2> _Sent2,
5085587Sobrien            weakly_incrementable _OutIter,
5185587Sobrien            class _Comp  = ranges::less,
5285587Sobrien            class _Proj1 = identity,
5385587Sobrien            class _Proj2 = identity>
5485587Sobrien    requires mergeable<_InIter1, _InIter2, _OutIter, _Comp, _Proj1, _Proj2>
5585587Sobrien  _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<_InIter1, _InIter2, _OutIter> operator()(
5685587Sobrien      _InIter1 __first1,
5785587Sobrien      _Sent1 __last1,
5885587Sobrien      _InIter2 __first2,
5985587Sobrien      _Sent2 __last2,
6085587Sobrien      _OutIter __result,
6185587Sobrien      _Comp __comp   = {},
6285587Sobrien      _Proj1 __proj1 = {},
6385587Sobrien      _Proj2 __proj2 = {}) const {
6485587Sobrien    auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>(
6585587Sobrien        std::move(__first1),
6685587Sobrien        std::move(__last1),
6785587Sobrien        std::move(__first2),
6885587Sobrien        std::move(__last2),
6985587Sobrien        std::move(__result),
7085587Sobrien        ranges::__make_projected_comp(__comp, __proj1, __proj2));
7185587Sobrien    return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)};
7285587Sobrien  }
7385587Sobrien
7485587Sobrien  template <input_range _Range1,
7585587Sobrien            input_range _Range2,
7685587Sobrien            weakly_incrementable _OutIter,
7785587Sobrien            class _Comp  = ranges::less,
7885587Sobrien            class _Proj1 = identity,
7985587Sobrien            class _Proj2 = identity>
8085587Sobrien    requires mergeable<iterator_t<_Range1>, iterator_t<_Range2>, _OutIter, _Comp, _Proj1, _Proj2>
8185587Sobrien  _LIBCPP_HIDE_FROM_ABI constexpr set_symmetric_difference_result<borrowed_iterator_t<_Range1>,
8285587Sobrien                                                                  borrowed_iterator_t<_Range2>,
8385587Sobrien                                                                  _OutIter>
8485587Sobrien  operator()(_Range1&& __range1,
8585587Sobrien             _Range2&& __range2,
8685587Sobrien             _OutIter __result,
8785587Sobrien             _Comp __comp   = {},
8885587Sobrien             _Proj1 __proj1 = {},
8985587Sobrien             _Proj2 __proj2 = {}) const {
9085587Sobrien    auto __ret = std::__set_symmetric_difference<_RangeAlgPolicy>(
9185587Sobrien        ranges::begin(__range1),
9285587Sobrien        ranges::end(__range1),
9385587Sobrien        ranges::begin(__range2),
9485587Sobrien        ranges::end(__range2),
9585587Sobrien        std::move(__result),
9685587Sobrien        ranges::__make_projected_comp(__comp, __proj1, __proj2));
9785587Sobrien    return {std::move(__ret.__in1_), std::move(__ret.__in2_), std::move(__ret.__out_)};
9885587Sobrien  }
9985587Sobrien};
10085587Sobrien
10185587Sobrien} // namespace __set_symmetric_difference
10285587Sobrien
10385587Sobrieninline namespace __cpo {
10485587Sobrieninline constexpr auto set_symmetric_difference = __set_symmetric_difference::__fn{};
10585587Sobrien} // namespace __cpo
10685587Sobrien} // namespace ranges
10785587Sobrien
10885587Sobrien_LIBCPP_END_NAMESPACE_STD
10985587Sobrien
11085587Sobrien#endif // _LIBCPP_STD_VER >= 20
11185587Sobrien
11285587Sobrien_LIBCPP_POP_MACROS
11385587Sobrien
11485587Sobrien#endif // _LIBCPP___ALGORITHM_RANGES_SET_SYMMETRIC_DIFFERENCE_H
11585587Sobrien