xref: /llvm-project/libcxx/include/__algorithm/ranges_clamp.h (revision d10dc5a06fac4dcabf2264c64c8672c6f6ae36fb)
1a203acb9SNikolas Klauser //===----------------------------------------------------------------------===//
2a203acb9SNikolas Klauser //
3a203acb9SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a203acb9SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
5a203acb9SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a203acb9SNikolas Klauser //
7a203acb9SNikolas Klauser //===----------------------------------------------------------------------===//
8a203acb9SNikolas Klauser 
9a203acb9SNikolas Klauser #ifndef _LIBCPP___ALGORITHM_RANGES_CLAMP_H
10a203acb9SNikolas Klauser #define _LIBCPP___ALGORITHM_RANGES_CLAMP_H
11a203acb9SNikolas Klauser 
12a203acb9SNikolas Klauser #include <__assert>
13a203acb9SNikolas Klauser #include <__config>
14a203acb9SNikolas Klauser #include <__functional/identity.h>
15a203acb9SNikolas Klauser #include <__functional/invoke.h>
16a203acb9SNikolas Klauser #include <__functional/ranges_operations.h>
17a203acb9SNikolas Klauser #include <__iterator/concepts.h>
18a203acb9SNikolas Klauser #include <__iterator/projected.h>
19a203acb9SNikolas Klauser #include <__utility/forward.h>
20a203acb9SNikolas Klauser 
21a203acb9SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22a203acb9SNikolas Klauser #  pragma GCC system_header
23a203acb9SNikolas Klauser #endif
24a203acb9SNikolas Klauser 
257b462251SLouis Dionne _LIBCPP_PUSH_MACROS
267b462251SLouis Dionne #include <__undef_macros>
277b462251SLouis Dionne 
284f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20
29a203acb9SNikolas Klauser 
30a203acb9SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
31a203acb9SNikolas Klauser 
32a203acb9SNikolas Klauser namespace ranges {
33*d10dc5a0SChristopher Di Bella struct __clamp {
34a203acb9SNikolas Klauser   template <class _Type,
35a203acb9SNikolas Klauser             class _Proj                                                      = identity,
36a203acb9SNikolas Klauser             indirect_strict_weak_order<projected<const _Type*, _Proj>> _Comp = ranges::less>
3783bc7b57SNikolas Klauser   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const _Type& operator()(
385aa03b64SLouis Dionne       const _Type& __value, const _Type& __low, const _Type& __high, _Comp __comp = {}, _Proj __proj = {}) const {
39dc577520SKonstantin Varlamov     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
40dc577520SKonstantin Varlamov         !bool(std::invoke(__comp, std::invoke(__proj, __high), std::invoke(__proj, __low))),
41a203acb9SNikolas Klauser         "Bad bounds passed to std::ranges::clamp");
42a203acb9SNikolas Klauser 
43979c19abSLouis Dionne     auto&& __projected = std::invoke(__proj, __value);
44979c19abSLouis Dionne     if (std::invoke(__comp, std::forward<decltype(__projected)>(__projected), std::invoke(__proj, __low)))
45a203acb9SNikolas Klauser       return __low;
46979c19abSLouis Dionne     else if (std::invoke(__comp, std::invoke(__proj, __high), std::forward<decltype(__projected)>(__projected)))
47a203acb9SNikolas Klauser       return __high;
48a203acb9SNikolas Klauser     else
49a203acb9SNikolas Klauser       return __value;
50a203acb9SNikolas Klauser   }
51a203acb9SNikolas Klauser };
52a203acb9SNikolas Klauser 
53a203acb9SNikolas Klauser inline namespace __cpo {
54*d10dc5a0SChristopher Di Bella inline constexpr auto clamp = __clamp{};
55a203acb9SNikolas Klauser } // namespace __cpo
56a203acb9SNikolas Klauser } // namespace ranges
57a203acb9SNikolas Klauser 
58a203acb9SNikolas Klauser _LIBCPP_END_NAMESPACE_STD
59a203acb9SNikolas Klauser 
604f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20
61a203acb9SNikolas Klauser 
627b462251SLouis Dionne _LIBCPP_POP_MACROS
637b462251SLouis Dionne 
64a203acb9SNikolas Klauser #endif // _LIBCPP___ALGORITHM_RANGES_CLAMP_H
65