xref: /llvm-project/libcxx/include/__algorithm/ranges_min.h (revision d10dc5a06fac4dcabf2264c64c8672c6f6ae36fb)
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