1f83d833eSNikolas Klauser //===----------------------------------------------------------------------===// 2f83d833eSNikolas Klauser // 3f83d833eSNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4f83d833eSNikolas Klauser // See https://llvm.org/LICENSE.txt for license information. 5f83d833eSNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6f83d833eSNikolas Klauser // 7f83d833eSNikolas Klauser //===----------------------------------------------------------------------===// 8f83d833eSNikolas Klauser 9f83d833eSNikolas Klauser #ifndef _LIBCPP___ALGORITHM_RANGES_MIN_H 10f83d833eSNikolas Klauser #define _LIBCPP___ALGORITHM_RANGES_MIN_H 11f83d833eSNikolas Klauser 12f83d833eSNikolas Klauser #include <__algorithm/ranges_min_element.h> 13f83d833eSNikolas Klauser #include <__assert> 14f83d833eSNikolas Klauser #include <__concepts/copyable.h> 15f83d833eSNikolas Klauser #include <__config> 16f83d833eSNikolas Klauser #include <__functional/identity.h> 17f83d833eSNikolas Klauser #include <__functional/invoke.h> 18f83d833eSNikolas Klauser #include <__functional/ranges_operations.h> 19f83d833eSNikolas Klauser #include <__iterator/concepts.h> 20f83d833eSNikolas Klauser #include <__iterator/projected.h> 21f83d833eSNikolas Klauser #include <__ranges/access.h> 22f83d833eSNikolas Klauser #include <__ranges/concepts.h> 23aff3cdc6SNikolas Klauser #include <__type_traits/is_trivially_copyable.h> 24f83d833eSNikolas Klauser #include <initializer_list> 25f83d833eSNikolas Klauser 26f83d833eSNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 27f83d833eSNikolas Klauser # pragma GCC system_header 28f83d833eSNikolas Klauser #endif 29f83d833eSNikolas Klauser 304f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 31f83d833eSNikolas Klauser 32f83d833eSNikolas Klauser _LIBCPP_PUSH_MACROS 33f83d833eSNikolas Klauser # include <__undef_macros> 34f83d833eSNikolas Klauser 35f83d833eSNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD 36f83d833eSNikolas Klauser 37f83d833eSNikolas Klauser namespace ranges { 38*d10dc5a0SChristopher Di Bella struct __min { 395aa03b64SLouis Dionne template <class _Tp, 405aa03b64SLouis Dionne class _Proj = identity, 41f83d833eSNikolas Klauser indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> 4283bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& 435aa03b64SLouis Dionne operator()(_LIBCPP_LIFETIMEBOUND const _Tp& __a, 44934650b2SNikolas Klauser _LIBCPP_LIFETIMEBOUND const _Tp& __b, 45934650b2SNikolas Klauser _Comp __comp = {}, 46934650b2SNikolas Klauser _Proj __proj = {}) const { 47f83d833eSNikolas Klauser return std::invoke(__comp, std::invoke(__proj, __b), std::invoke(__proj, __a)) ? __b : __a; 48f83d833eSNikolas Klauser } 49f83d833eSNikolas Klauser 505aa03b64SLouis Dionne template <copyable _Tp, 515aa03b64SLouis Dionne class _Proj = identity, 52f83d833eSNikolas Klauser indirect_strict_weak_order<projected<const _Tp*, _Proj>> _Comp = ranges::less> 5383bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp 545aa03b64SLouis Dionne operator()(initializer_list<_Tp> __il, _Comp __comp = {}, _Proj __proj = {}) const { 551638657dSKonstantin Varlamov _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( 561638657dSKonstantin Varlamov __il.begin() != __il.end(), "initializer_list must contain at least one element"); 57f83d833eSNikolas Klauser return *ranges::__min_element_impl(__il.begin(), __il.end(), __comp, __proj); 58f83d833eSNikolas Klauser } 59f83d833eSNikolas Klauser 605aa03b64SLouis Dionne template <input_range _Rp, 615aa03b64SLouis Dionne class _Proj = identity, 62f83d833eSNikolas Klauser indirect_strict_weak_order<projected<iterator_t<_Rp>, _Proj>> _Comp = ranges::less> 63f83d833eSNikolas Klauser requires indirectly_copyable_storable<iterator_t<_Rp>, range_value_t<_Rp>*> 6483bc7b57SNikolas Klauser [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr range_value_t<_Rp> 655aa03b64SLouis Dionne operator()(_Rp&& __r, _Comp __comp = {}, _Proj __proj = {}) const { 66f83d833eSNikolas Klauser auto __first = ranges::begin(__r); 67f83d833eSNikolas Klauser auto __last = ranges::end(__r); 681638657dSKonstantin Varlamov _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__first != __last, "range must contain at least one element"); 69aff3cdc6SNikolas Klauser if constexpr (forward_range<_Rp> && !__is_cheap_to_copy<range_value_t<_Rp>>) { 70f83d833eSNikolas Klauser return *ranges::__min_element_impl(__first, __last, __comp, __proj); 71f83d833eSNikolas Klauser } else { 72f83d833eSNikolas Klauser range_value_t<_Rp> __result = *__first; 73f83d833eSNikolas Klauser while (++__first != __last) { 74f83d833eSNikolas Klauser if (std::invoke(__comp, std::invoke(__proj, *__first), std::invoke(__proj, __result))) 75f83d833eSNikolas Klauser __result = *__first; 76f83d833eSNikolas Klauser } 77f83d833eSNikolas Klauser return __result; 78f83d833eSNikolas Klauser } 79f83d833eSNikolas Klauser } 80f83d833eSNikolas Klauser }; 81f83d833eSNikolas Klauser 82f83d833eSNikolas Klauser inline namespace __cpo { 83*d10dc5a0SChristopher Di Bella inline constexpr auto min = __min{}; 84f83d833eSNikolas Klauser } // namespace __cpo 85f83d833eSNikolas Klauser } // namespace ranges 86f83d833eSNikolas Klauser 87f83d833eSNikolas Klauser _LIBCPP_END_NAMESPACE_STD 88f83d833eSNikolas Klauser 89f83d833eSNikolas Klauser _LIBCPP_POP_MACROS 90f83d833eSNikolas Klauser 9103a9f07eSLouis Dionne #endif // _LIBCPP_STD_VER >= 20 92f83d833eSNikolas Klauser 93f83d833eSNikolas Klauser #endif // _LIBCPP___ALGORITHM_RANGES_MIN_H 94