siplasplas
A library for C++ reflection and introspection
algorithm.hpp
1 #ifndef SIPLASPLAS_CONSTEXPR_ALGORITHM_HPP
2 #define SIPLASPLAS_CONSTEXPR_ALGORITHM_HPP
3 
4 #include <cstdint>
5 #include <type_traits>
6 
7 namespace cpp
8 {
9 
10 namespace constexp
11 {
12 
26 struct Equal
27 {
28  constexpr Equal() = default;
29 
30  template<typename T, typename U>
31  constexpr bool operator()(const T& lhs, const U& rhs) const
32  {
33  return lhs == rhs;
34  }
35 };
36 
44 struct NotEqual
45 {
46  constexpr NotEqual() = default;
47 
48  template<typename T, typename U>
49  constexpr bool operator()(const T& lhs, const U& rhs) const
50  {
51  return lhs != rhs;
52  }
53 };
54 
61 template<typename Sequence>
62 constexpr auto begin(const Sequence& sequence)
63 {
64  return sequence.begin();
65 }
66 
73 template<typename T, std::size_t N>
74 constexpr auto begin(const T (&array)[N])
75 {
76  return &array[0];
77 }
78 
85 template<typename Sequence>
86 constexpr auto end(const Sequence& sequence)
87 {
88  return sequence.end();
89 }
90 
97 template<typename T, std::size_t N>
98 constexpr auto end(const T (&array)[N])
99 {
100  return &array[N];
101 }
102 
107 template<typename Begin, typename End>
108 constexpr auto distance(Begin begin, End end)
109 {
110  return end - begin;
111 }
112 
132 template<
133  typename Begin1, typename End1,
134  typename Begin2, typename End2,
135  typename Compare
136 >
137 constexpr bool equal(
138  Begin1 begin1, End1 end1,
139  Begin2 begin2, End2 end2,
140  Compare compare
141 )
142 {
143  return (begin1 == end1 || begin2 == end2) ?
144  ((::cpp::constexp::distance(begin1, end1) !=
145  ::cpp::constexp::distance(begin2, end2)) ?
146  false
147  :
148  true
149  )
150  :
151  compare(*begin1++, *begin2++) &&
152  ::cpp::constexp::equal(begin1, end1, begin2, end2, compare);
153 }
154 
171 template<
172  typename Begin1, typename End1,
173  typename Begin2, typename End2
174 >
175 constexpr bool equal(
176  Begin1 begin1, End1 end1,
177  Begin2 begin2, End2 end2
178 )
179 {
180  return equal(
181  begin1, end1,
182  begin2, end2,
184  );
185 }
186 
197 template<typename Lhs, typename Rhs>
198 constexpr bool equal(const Lhs& lhs, const Rhs& rhs)
199 {
203  );
204 }
205 
211 template<typename T>
212 constexpr const T& max(const T& lhs, const T& rhs)
213 {
214  return lhs >= rhs ?
215  lhs
216  :
217  rhs;
218 }
219 
225 template<typename T, typename U>
226 constexpr std::common_type_t<T, U> max(const T& lhs, const U& rhs)
227 {
228  return static_cast<std::common_type_t<T, U>>(lhs) >=
229  static_cast<std::common_type_t<T, U>>(rhs) ?
230  lhs
231  :
232  rhs;
233 }
234 
239 template<typename First, typename Second, typename Third, typename... Tail>
240 constexpr decltype(auto) max(const First& first, const Second& second, const Third& third,
241  const Tail&... tail)
242 {
244  first,
246  second,
247  third,
248  tail...
249  )
250  );
251 }
252 
253 
254 
260 template<typename T>
261 constexpr const T& min(const T& lhs, const T& rhs)
262 {
263  return lhs <= rhs ?
264  lhs
265  :
266  rhs;
267 }
268 
274 template<typename T, typename U>
275 constexpr std::common_type_t<T, U> min(const T& lhs, const U& rhs)
276 {
277  // The cast is needed to prevemt signed vs unsigned comparison
278  // warnings
279  return static_cast<std::common_type_t<T, U>>(lhs) <=
280  static_cast<std::common_type_t<T, U>>(rhs) ?
281  lhs
282  :
283  rhs;
284 }
285 
290 template<typename First, typename Second, typename Third, typename... Tail>
291 constexpr decltype(auto) min(const First& first, const Second& second, const Third& third,
292  const Tail&... tail)
293 {
295  first,
297  second,
298  third,
299  tail...
300  )
301  );
302 }
303 
304 
310 template<
311  typename Begin1, typename End1,
312  typename Begin2, typename End2
313 >
314 constexpr std::size_t levenshteinDistance(
315  Begin1 begin1, End1 end1,
316  Begin2 begin2, End2 end2
317 )
318 {
319  return (begin1 >= end1) ?
320  ::cpp::constexp::distance(begin2, end2)
321  :(
322  (begin2 >= end2) ?
323  ::cpp::constexp::distance(begin1, end1)
324  :(
326  ::cpp::constexp::levenshteinDistance(begin1 + 1, end1, begin2, end2) + 1,
327  ::cpp::constexp::levenshteinDistance(begin1, end1, begin2 + 1, end2) + 1,
328  ::cpp::constexp::levenshteinDistance(begin1 + 1, end1, begin2 + 1, end2) +
329  ((*begin1 == *begin2) ? 0 : 1)
330  )
331  ));
332 }
333 
339 template<typename Lhs, typename Rhs>
340 constexpr std::size_t levenshteinDistance(const Lhs& lhs, const Rhs& rhs)
341 {
343  ::cpp::constexp::begin(lhs),
344  ::cpp::constexp::end(lhs),
345  ::cpp::constexp::begin(rhs),
346  ::cpp::constexp::end(rhs)
347  );
348 }
349 
360 template<typename Iterator, typename T>
361 constexpr Iterator find(Iterator begin, Iterator end, const T& value)
362 {
363  return (begin == end) ? end :
364  (*begin == value) ? begin :
365  find(begin + 1, end, value);
366 }
367 
368 #ifndef SIPLASPLAS_CONSTEXPR_ALGORITHM_MAX_STRLEN_LENGTH
369 
382  constexpr std::size_t MAX_STRLEN_LENGTH = 1024 * 1024;
383 #else
384 
397  constexpr std::size_t MAX_STRLEN_LENGTH = SIPLASPLAS_CONSTEXPR_ALGORITHM_MAX_STRLEN_LENGTH;
398 #endif // SIPLASPLAS_CONSTEXPR_ALGORITHM_MAX_STRLEN_LENGTH
399 
409 constexpr std::size_t strlen(const char* str)
410 {
412  str,
413  ::cpp::constexp::find(str, str + ::cpp::constexp::MAX_STRLEN_LENGTH, '\0')
414  );
415 }
416 
417 }
418 
419 }
420 
421 #endif // SIPLASPLAS_CONSTEXPR_ALGORITHM_HPP
constexpr auto begin(const T(&array)[N])
Returns an iterator pointing to the beginning of an array.
Definition: algorithm.hpp:74
Constexpr functor that compares two values for equality.
Definition: algorithm.hpp:26
Definition: canary_allocator.hpp:7
decltype(auto) constexpr min(const First &first, const Second &second, const Third &third, const Tail &... tail)
Returns the smallest value of the set of values given.
Definition: algorithm.hpp:291
constexpr Iterator find(Iterator begin, Iterator end, const T &value)
Finds a value in a sequence.
Definition: algorithm.hpp:361
constexpr auto distance(Begin begin, End end)
Returns the distance between two iterators.
Definition: algorithm.hpp:108
constexpr auto end(const T(&array)[N])
Returns an iterator pointing to the end of an array.
Definition: algorithm.hpp:98
Constexpr functor that compares two values for inequality.
Definition: algorithm.hpp:44
decltype(auto) constexpr max(const First &first, const Second &second, const Third &third, const Tail &... tail)
Returns the greatest value of the set of values given.
Definition: algorithm.hpp:240
constexpr std::size_t levenshteinDistance(const Lhs &lhs, const Rhs &rhs)
Computes the distance between two sequences using the Levenshtein distance algorithm.
Definition: algorithm.hpp:340
constexpr bool equal(const Lhs &lhs, const Rhs &rhs)
Compares if two sequences are equal.
Definition: algorithm.hpp:198