1e476df56SNikolas Klauser //===----------------------------------------------------------------------===// 2e476df56SNikolas Klauser // 3e476df56SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e476df56SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5e476df56SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e476df56SNikolas Klauser // 7e476df56SNikolas Klauser //===----------------------------------------------------------------------===// 8e476df56SNikolas Klauser 9e476df56SNikolas Klauser #ifndef _LIBCPP___ALGORITHM_RANGES_MAX_H 10e476df56SNikolas Klauser #define _LIBCPP___ALGORITHM_RANGES_MAX_H 11e476df56SNikolas Klauser 12e476df56SNikolas Klauser #include <__algorithm/ranges_min_element.h> 13e476df56SNikolas Klauser #include <__assert> 14e476df56SNikolas Klauser #include <__concepts/copyable.h> 15e476df56SNikolas Klauser #include <__config> 16e476df56SNikolas Klauser #include <__functional/identity.h> 17e476df56SNikolas Klauser #include <__functional/invoke.h> 18e476df56SNikolas Klauser #include <__functional/ranges_operations.h> 19e476df56SNikolas Klauser #include <__iterator/concepts.h> 20e476df56SNikolas Klauser #include <__iterator/projected.h> 21e476df56SNikolas Klauser #include <__ranges/access.h> 22e476df56SNikolas Klauser #include <__ranges/concepts.h> 23aff3cdc6SNikolas Klauser #include <__type_traits/is_trivially_copyable.h> 24e476df56SNikolas Klauser #include <__utility/move.h> 25e476df56SNikolas Klauser #include <initializer_list> 26e476df56SNikolas Klauser 27e476df56SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 28e476df56SNikolas Klauser # pragma GCC system_header 29e476df56SNikolas Klauser #endif 30e476df56SNikolas Klauser 314f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 32e476df56SNikolas Klauser 33e476df56SNikolas Klauser _LIBCPP_PUSH_MACROS 34e476df56SNikolas Klauser # include <__undef_macros> 35e476df56SNikolas Klauser 36e476df56SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 37e476df56SNikolas Klauser 38e476df56SNikolas Klauser namespace ranges { 39*d10dc5a0SChristopher Di Bella struct __max { 405aa03b64SLouis Dionne template <class _Tp, 415aa03b64SLouis Dionne class _Proj = identity, 42e476df56SNikolas Klauser indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> 4383bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& 445aa03b64SLouis Dionne operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, 45934650b2SNikolas Klauser _LIBCPP_LIFETIMEBOUND const _Tp& __b, 46934650b2SNikolas Klauser _Comp __comp = {}, 47934650b2SNikolas Klauser _Proj __proj = {}) const { 48e476df56SNikolas Klauser return std::invoke(__comp, std::invoke(__proj, __a), std::invoke(__proj, __b)) ? __b : __a; 49e476df56SNikolas Klauser } 50e476df56SNikolas Klauser 515aa03b64SLouis Dionne template <copyable _Tp, 525aa03b64SLouis Dionne class _Proj = identity, 53e476df56SNikolas Klauser indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> 5483bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp 555aa03b64SLouis Dionne operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { 561638657dSKonstantin Varlamov _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 571638657dSKonstantin Varlamov __il.begin() != __il.end(), "initializer_list must contain at least one element"); 58e476df56SNikolas Klauser 5902540b2fSLouis Dionne auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { return std::invoke(__comp, __rhs, __lhs); }; 60e476df56SNikolas Klauser return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp_lhs_rhs_swapped, __proj); 61e476df56SNikolas Klauser } 62e476df56SNikolas Klauser 635aa03b64SLouis Dionne template <input_range _Rp, 645aa03b64SLouis Dionne class _Proj = identity, 65e476df56SNikolas Klauser indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> 66e476df56SNikolas Klauser requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*> 6783bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> 685aa03b64SLouis Dionne operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { 69e476df56SNikolas Klauser auto __first = ranges::begin(__r); 70e476df56SNikolas Klauser auto __last = ranges::end(__r); 71e476df56SNikolas Klauser 721638657dSKonstantin Varlamov _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__first != __last, "range must contain at least one element"); 73e476df56SNikolas Klauser 74aff3cdc6SNikolas Klauser if constexpr (forward_range<_Rp> && !__is_cheap_to_copy<range_value_t<_Rp>>) { 7502540b2fSLouis Dionne auto __comp_lhs_rhs_swapped = [&](auto&& __lhs, auto&& __rhs) -> bool { 7602540b2fSLouis Dionne return std::invoke(__comp, __rhs, __lhs); 7702540b2fSLouis Dionne }; 78e476df56SNikolas Klauser return *ranges::__min_element_impl(std::move(__first), std::move(__last), __comp_lhs_rhs_swapped, __proj); 79e476df56SNikolas Klauser } else { 80e476df56SNikolas Klauser range_value_t<_Rp> __result = *__first; 81e476df56SNikolas Klauser while (++__first != __last) { 82e476df56SNikolas Klauser if (std::invoke(__comp, std::invoke(__proj, __result), std::invoke(__proj, *__first))) 83e476df56SNikolas Klauser __result = *__first; 84e476df56SNikolas Klauser } 85e476df56SNikolas Klauser return __result; 86e476df56SNikolas Klauser } 87e476df56SNikolas Klauser } 88e476df56SNikolas Klauser }; 89e476df56SNikolas Klauser 90e476df56SNikolas Klauser inline namespace __cpo { 91*d10dc5a0SChristopher Di Bella inline constexpr auto max = __max{}; 92e476df56SNikolas Klauser } // namespace __cpo 93e476df56SNikolas Klauser } // namespace ranges 94e476df56SNikolas Klauser 95e476df56SNikolas Klauser _LIBCPP_END_NAMESPACE_STD 96e476df56SNikolas Klauser 97e476df56SNikolas Klauser _LIBCPP_POP_MACROS 98e476df56SNikolas Klauser 9903a9f07eSLouis Dionne #endif // _LIBCPP_STD_VER >= 20 100e476df56SNikolas Klauser 101e476df56SNikolas Klauser #endif // _LIBCPP___ALGORITHM_RANGES_MAX_H 102