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