xref: /llvm-project/libcxx/include/__algorithm/min_element.h (revision 09e3a360581dc36d0820d3fb6da9bd7cfed87b5d)
1134723edSLouis Dionne //===----------------------------------------------------------------------===//
2134723edSLouis Dionne //
3134723edSLouis Dionne // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4134723edSLouis Dionne // See https://llvm.org/LICENSE.txt for license information.
5134723edSLouis Dionne // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6134723edSLouis Dionne //
7134723edSLouis Dionne //===----------------------------------------------------------------------===//
8134723edSLouis Dionne 
9134723edSLouis Dionne #ifndef _LIBCPP___ALGORITHM_MIN_ELEMENT_H
10134723edSLouis Dionne #define _LIBCPP___ALGORITHM_MIN_ELEMENT_H
11134723edSLouis Dionne 
12134723edSLouis Dionne #include <__algorithm/comp.h>
13b07b5bd7SArthur O'Dwyer #include <__algorithm/comp_ref_type.h>
144d81a46fSArthur O'Dwyer #include <__config>
15a7c3379cSKonstantin Varlamov #include <__functional/identity.h>
16134723edSLouis Dionne #include <__iterator/iterator_traits.h>
17*09e3a360SLouis Dionne #include <__type_traits/invoke.h>
18a7c3379cSKonstantin Varlamov #include <__type_traits/is_callable.h>
19a7c3379cSKonstantin Varlamov #include <__utility/move.h>
20134723edSLouis Dionne 
21134723edSLouis Dionne #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22134723edSLouis Dionne #  pragma GCC system_header
23134723edSLouis Dionne #endif
24134723edSLouis Dionne 
2592e4d679SNicole Rabjohn _LIBCPP_PUSH_MACROS
2692e4d679SNicole Rabjohn #include <__undef_macros>
2792e4d679SNicole Rabjohn 
28134723edSLouis Dionne _LIBCPP_BEGIN_NAMESPACE_STD
29134723edSLouis Dionne 
30a7c3379cSKonstantin Varlamov template <class _Comp, class _Iter, class _Sent, class _Proj>
319783f28cSLouis Dionne inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter
329783f28cSLouis Dionne __min_element(_Iter __first, _Sent __last, _Comp __comp, _Proj& __proj) {
33a7c3379cSKonstantin Varlamov   if (__first == __last)
34134723edSLouis Dionne     return __first;
35a7c3379cSKonstantin Varlamov 
36a7c3379cSKonstantin Varlamov   _Iter __i = __first;
37a7c3379cSKonstantin Varlamov   while (++__i != __last)
38a7c3379cSKonstantin Varlamov     if (std::__invoke(__comp, std::__invoke(__proj, *__i), std::__invoke(__proj, *__first)))
39a7c3379cSKonstantin Varlamov       __first = __i;
40a7c3379cSKonstantin Varlamov 
41a7c3379cSKonstantin Varlamov   return __first;
42a7c3379cSKonstantin Varlamov }
43a7c3379cSKonstantin Varlamov 
44a7c3379cSKonstantin Varlamov template <class _Comp, class _Iter, class _Sent>
459783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Iter __min_element(_Iter __first, _Sent __last, _Comp __comp) {
46a7c3379cSKonstantin Varlamov   auto __proj = __identity();
47a7c3379cSKonstantin Varlamov   return std::__min_element<_Comp>(std::move(__first), std::move(__last), __comp, __proj);
48134723edSLouis Dionne }
49134723edSLouis Dionne 
50b07b5bd7SArthur O'Dwyer template <class _ForwardIterator, class _Compare>
5117e0686aSNikolas Klauser [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
529783f28cSLouis Dionne min_element(_ForwardIterator __first, _ForwardIterator __last, _Compare __comp) {
539783f28cSLouis Dionne   static_assert(
549783f28cSLouis Dionne       __has_forward_iterator_category<_ForwardIterator>::value, "std::min_element requires a ForwardIterator");
559783f28cSLouis Dionne   static_assert(
5625783158SLouis Dionne       __is_callable<_Compare&, decltype(*__first), decltype(*__first)>::value, "The comparator has to be callable");
57a7c3379cSKonstantin Varlamov 
58ed2d3644SNikolas Klauser   return std::__min_element<__comp_ref_type<_Compare> >(std::move(__first), std::move(__last), __comp);
59b07b5bd7SArthur O'Dwyer }
60b07b5bd7SArthur O'Dwyer 
61134723edSLouis Dionne template <class _ForwardIterator>
6217e0686aSNikolas Klauser [[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _ForwardIterator
639783f28cSLouis Dionne min_element(_ForwardIterator __first, _ForwardIterator __last) {
6477a00c0dSLouis Dionne   return std::min_element(__first, __last, __less<>());
65134723edSLouis Dionne }
66134723edSLouis Dionne 
67134723edSLouis Dionne _LIBCPP_END_NAMESPACE_STD
68134723edSLouis Dionne 
6992e4d679SNicole Rabjohn _LIBCPP_POP_MACROS
7092e4d679SNicole Rabjohn 
71134723edSLouis Dionne #endif // _LIBCPP___ALGORITHM_MIN_ELEMENT_H
72