VCCC  2024.05
VisualCamp Common C++ library
min.hpp
Go to the documentation of this file.
1 //
2 // Created by YongGyu Lee on 12/28/23.
3 //
4 
5 #ifndef VCCC_ALGORITHM_RANGES_MIN_HPP
6 #define VCCC_ALGORITHM_RANGES_MIN_HPP
7 
8 #include <functional>
9 #include <initializer_list>
10 
25 
26 namespace vccc {
27 namespace ranges {
28 namespace detail {
29 
30 struct min_niebloid {
31  private:
32  template<typename R, typename Proj, typename Comp, bool = projectable<iterator_t<R>, Proj>::value /* false */>
33  struct check_range_2 : std::false_type {};
34  template<typename R, typename Proj, typename Comp>
35  struct check_range_2<R, Proj, Comp, true>
36  : conjunction<
37  indirect_strict_weak_order<Comp, projected<iterator_t<R>, Proj>>,
38  indirectly_copyable_storable<iterator_t<R>, range_value_t<R>*>
39  > {};
40 
42  struct check_range : std::false_type {};
43  template<typename R, typename Proj, typename Comp>
44  struct check_range<R, Proj, Comp, true> : check_range_2<R, Proj, Comp> {};
45 
46  template<typename R, typename Proj, typename Comp>
47  constexpr range_value_t<R> min_range(R&& r, Comp comp, Proj proj, std::true_type /* forward_range */) const {
48  return static_cast<range_value_t<R>>(*ranges::min_element(r, std::ref(comp), std::ref(proj)));
49  }
50 
51  template<typename R, typename Proj, typename Comp>
52  constexpr range_value_t<R> min_range(R&& r, Comp comp, Proj proj, std::false_type /* forward_range */) const {
53  auto i = ranges::begin(r);
54  auto s = ranges::end(r);
55  range_value_t<R> m(*i);
56  while (++i != s) {
57  if (!vccc::invoke(comp, vccc::invoke(proj, *i), vccc::invoke(proj, m)))
58  m = *i;
59  }
60  return m;
61  }
62 
63  public:
64  template<typename T, typename Proj = identity, typename Comp = less,
65  std::enable_if_t<indirect_strict_weak_order<Comp, projected<const T*, Proj>>::value, int> = 0>
66  constexpr const T& operator()(const T& a, const T& b, Comp comp = {}, Proj proj = {}) const {
67  return vccc::invoke(comp, vccc::invoke(proj, a), vccc::invoke(proj, b)) ? a : b;
68  }
69 
70  template<typename T, typename Proj = identity, typename Comp = less, std::enable_if_t<conjunction<
71  copyable<T>,
72  indirect_strict_weak_order<Comp, projected<const T*, Proj>>
73  >::value, int> = 0>
74  constexpr T operator()(std::initializer_list<T> r, Comp comp = {}, Proj proj = {}) const {
75  return *ranges::min_element(r, std::ref(comp), std::ref(proj));
76  }
77 
78  template<typename R, typename Proj = identity, typename Comp = less, std::enable_if_t<
79  check_range<R, Proj, Comp>
80  ::value, int> = 0>
81  constexpr range_value_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
82  return this->min_range(std::forward<R>(r), std::ref(comp), std::ref(proj), forward_range<R>{});
83  }
84 };
85 } // namespace detail
86 
89 
90 VCCC_INLINE_OR_STATIC constexpr detail::min_niebloid min{};
91 
93 
94 } // namespace ranges
95 } // namespace vccc
96 
97 #endif // VCCC_ALGORITHM_RANGES_MIN_HPP
constexpr VCCC_INLINE_OR_STATIC detail::min_niebloid min
Definition: min.hpp:90
constexpr VCCC_INLINE_OR_STATIC detail::min_element_niebloid min_element
Definition: min_element.hpp:52
constexpr invoke_result_t< F, Args... > invoke(F &&f, Args &&... args) noexcept(is_nothrow_invocable< F, Args... >::value)
Definition: invoke.hpp:38
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
#define VCCC_INLINE_OR_STATIC
Definition: inline_or_static.hpp:9
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35