VCCC  2024.05
VisualCamp Common C++ library
equal.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 1/12/24.
3 //
4 
5 #ifndef VCCC_ALGORITHM_RANGES_EQUAL_HPP
6 #define VCCC_ALGORITHM_RANGES_EQUAL_HPP
7 
8 #include <functional>
9 #include <initializer_list>
10 #include <type_traits>
11 
21 #include "vccc/__ranges/begin.hpp"
23 #include "vccc/__ranges/end.hpp"
27 
28 namespace vccc {
29 namespace ranges {
30 namespace detail {
31 
32 struct equal_niebloid {
33  private:
34  template<typename R1, typename R2, typename Pred, typename Proj1, typename Proj2,
35  bool = conjunction<input_range<R1>, input_range<R2>>::value /* false */>
36  struct check_range : std::false_type {};
37  template<typename R1, typename R2, typename Pred, typename Proj1, typename Proj2>
38  struct check_range<R1, R2, Pred, Proj1, Proj2, true>
39  : indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> {};
40 
41  template<typename I1, typename S1, typename I2, typename S2>
42  constexpr bool compare_size(I1 first1, S1 last1, I2 first2, S2 last2, std::true_type /* sized_sentinel_for */) const {
43  return ranges::distance(first1, last1) == ranges::distance(first2, last2);
44  }
45  template<typename I1, typename S1, typename I2, typename S2>
46  constexpr bool compare_size(I1, S1, I2, S2, std::false_type /* sized_sentinel_for */) const {
47  return true;
48  }
49 
50  public:
55  template<
56  typename I1, typename S1,
57  typename I2, typename S2,
58  typename Pred = ranges::equal_to,
59  typename Proj1 = identity, typename Proj2 = identity,
60  std::enable_if_t<conjunction<
61  input_iterator<I1>, sentinel_for<S1, I1>,
62  input_iterator<I2>, sentinel_for<S2, I2>,
63  indirectly_comparable<I1, I2, Pred, Proj1, Proj2>
64  >::value, int> = 0
65  >
66  VCCC_NODISCARD constexpr bool
67  operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const {
68  if (!compare_size(first1, last1, first2, last2, conjunction<sized_sentinel_for<S1, I1>, sized_sentinel_for<S2, I2>>{}))
69  return false;
70 
71  for (; first1 != last1; ++first1, (void)++first2) {
72  if (!vccc::invoke(pred, vccc::invoke(proj1, *first1), vccc::invoke(proj2, *first2)))
73  return false;
74  }
75  return true;
76  }
77 
82  template<
83  typename R1,
84  typename R2,
85  typename Pred = ranges::equal_to,
86  typename Proj1 = vccc::identity, typename Proj2 = vccc::identity,
88  >
89  VCCC_NODISCARD constexpr bool
90  operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const {
91  return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2),
92  std::ref(pred), std::ref(proj1), std::ref(proj2));
93  }
94 
95  template<
96  typename T,
97  typename R2,
98  typename Pred = equal_to,
99  typename Proj1 = identity, typename Proj2 = identity,
100  std::enable_if_t<check_range<std::initializer_list<T>, R2, Pred, Proj1, Proj2>::value, int> = 0
101  >
102  VCCC_NODISCARD constexpr bool
103  operator()(std::initializer_list<T>&& il, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const {
104  return (*this)(ranges::begin(il), ranges::end(il), ranges::begin(r2), ranges::end(r2),
105  std::ref(pred), std::ref(proj1), std::ref(proj2));
106  }
107 
108  template<
109  typename R1,
110  typename U,
111  typename Pred = equal_to,
112  typename Proj1 = identity, typename Proj2 = identity,
113  std::enable_if_t<check_range<R1, std::initializer_list<U>, Pred, Proj1, Proj2>::value, int> = 0
114  >
115  VCCC_NODISCARD constexpr bool
116  operator()(R1&& r1, std::initializer_list<U> il, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const {
117  return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(il), ranges::end(il),
118  std::ref(pred), std::ref(proj1), std::ref(proj2));
119  }
120 
121  template<
122  typename T,
123  typename U,
124  typename Pred = equal_to,
125  typename Proj1 = identity, typename Proj2 = identity,
126  std::enable_if_t<check_range<std::initializer_list<T>, std::initializer_list<U>, Pred, Proj1, Proj2>::value, int> = 0
127  >
128  VCCC_NODISCARD constexpr bool
129  operator()(std::initializer_list<T> il1, std::initializer_list<U> il2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const {
130  return (*this)(ranges::begin(il1), ranges::end(il1), ranges::begin(il2), ranges::end(il2),
131  std::ref(pred), std::ref(proj1), std::ref(proj2));
132  }
133 };
134 
135 } // namespace detail
136 
139 
142 VCCC_INLINE_OR_STATIC constexpr detail::equal_niebloid equal{};
143 
145 
146 } // namespace ranges
147 } // namespace vccc
148 
149 #endif // VCCC_ALGORITHM_RANGES_EQUAL_HPP
constexpr VCCC_INLINE_OR_STATIC detail::equal_niebloid equal
Two ranges are considered equal if they have the same number of elements and every pair of correspond...
Definition: equal.hpp:142
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::distance_niebloid distance
Definition: distance.hpp:72
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
#define VCCC_NODISCARD
Definition: nodiscard.hpp:14
function object that returns its argument unchanged
Definition: identity.hpp:25