algorithm.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*!
  2. @file
  3. Defines several `constexpr` algorithms.
  4. @copyright Louis Dionne 2013-2017
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_DETAIL_ALGORITHM_HPP
  9. #define BOOST_HANA_DETAIL_ALGORITHM_HPP
  10. #include <boost/hana/functional/placeholder.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <cstddef>
  13. #include <utility>
  14. BOOST_HANA_NAMESPACE_BEGIN namespace detail {
  15. // Do not call this swap, otherwise it can get picked up by ADL and conflict
  16. // with std::swap (see https://github.com/boostorg/hana/issues/297).
  17. template <typename T>
  18. constexpr void constexpr_swap(T& x, T& y) {
  19. auto tmp = x;
  20. x = y;
  21. y = std::move(tmp);
  22. }
  23. template <typename BidirIter>
  24. constexpr void reverse(BidirIter first, BidirIter last) {
  25. while (first != last) {
  26. if (first == --last)
  27. break;
  28. detail::constexpr_swap(*first, *last);
  29. ++first;
  30. }
  31. }
  32. template <typename BidirIter, typename BinaryPred>
  33. constexpr bool next_permutation(BidirIter first, BidirIter last,
  34. BinaryPred pred)
  35. {
  36. BidirIter i = last;
  37. if (first == last || first == --i)
  38. return false;
  39. while (true) {
  40. BidirIter ip1 = i;
  41. if (pred(*--i, *ip1)) {
  42. BidirIter j = last;
  43. while (!pred(*i, *--j))
  44. ;
  45. detail::constexpr_swap(*i, *j);
  46. detail::reverse(ip1, last);
  47. return true;
  48. }
  49. if (i == first) {
  50. detail::reverse(first, last);
  51. return false;
  52. }
  53. }
  54. }
  55. template <typename BidirIter>
  56. constexpr bool next_permutation(BidirIter first, BidirIter last)
  57. { return detail::next_permutation(first, last, hana::_ < hana::_); }
  58. template <typename InputIter1, typename InputIter2, typename BinaryPred>
  59. constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
  60. InputIter2 first2, InputIter2 last2,
  61. BinaryPred pred)
  62. {
  63. for (; first2 != last2; ++first1, ++first2) {
  64. if (first1 == last1 || pred(*first1, *first2))
  65. return true;
  66. else if (pred(*first2, *first1))
  67. return false;
  68. }
  69. return false;
  70. }
  71. template <typename InputIter1, typename InputIter2>
  72. constexpr bool lexicographical_compare(InputIter1 first1, InputIter1 last1,
  73. InputIter2 first2, InputIter2 last2)
  74. { return detail::lexicographical_compare(first1, last1, first2, last2, hana::_ < hana::_); }
  75. template <typename InputIter1, typename InputIter2, typename BinaryPred>
  76. constexpr bool equal(InputIter1 first1, InputIter1 last1,
  77. InputIter2 first2, InputIter2 last2,
  78. BinaryPred pred)
  79. {
  80. for (; first1 != last1 && first2 != last2; ++first1, ++first2)
  81. if (!pred(*first1, *first2))
  82. return false;
  83. return first1 == last1 && first2 == last2;
  84. }
  85. template <typename InputIter1, typename InputIter2>
  86. constexpr bool equal(InputIter1 first1, InputIter1 last1,
  87. InputIter2 first2, InputIter2 last2)
  88. { return detail::equal(first1, last1, first2, last2, hana::_ == hana::_); }
  89. template <typename BidirIter, typename BinaryPred>
  90. constexpr void sort(BidirIter first, BidirIter last, BinaryPred pred) {
  91. if (first == last) return;
  92. BidirIter i = first;
  93. for (++i; i != last; ++i) {
  94. BidirIter j = i;
  95. auto t = *j;
  96. for (BidirIter k = i; k != first && pred(t, *--k); --j)
  97. *j = *k;
  98. *j = t;
  99. }
  100. }
  101. template <typename BidirIter>
  102. constexpr void sort(BidirIter first, BidirIter last)
  103. { detail::sort(first, last, hana::_ < hana::_); }
  104. template <typename InputIter, typename T>
  105. constexpr InputIter find(InputIter first, InputIter last, T const& value) {
  106. for (; first != last; ++first)
  107. if (*first == value)
  108. return first;
  109. return last;
  110. }
  111. template <typename InputIter, typename UnaryPred>
  112. constexpr InputIter find_if(InputIter first, InputIter last, UnaryPred pred) {
  113. for (; first != last; ++first)
  114. if (pred(*first))
  115. return first;
  116. return last;
  117. }
  118. template <typename ForwardIter, typename T>
  119. constexpr void iota(ForwardIter first, ForwardIter last, T value) {
  120. while (first != last) {
  121. *first++ = value;
  122. ++value;
  123. }
  124. }
  125. template <typename InputIt, typename T>
  126. constexpr std::size_t
  127. count(InputIt first, InputIt last, T const& value) {
  128. std::size_t n = 0;
  129. for (; first != last; ++first)
  130. if (*first == value)
  131. ++n;
  132. return n;
  133. }
  134. template <typename InputIt, typename T, typename F>
  135. constexpr T accumulate(InputIt first, InputIt last, T init, F f) {
  136. for (; first != last; ++first)
  137. init = f(init, *first);
  138. return init;
  139. }
  140. template <typename InputIt, typename T>
  141. constexpr T accumulate(InputIt first, InputIt last, T init) {
  142. return detail::accumulate(first, last, init, hana::_ + hana::_);
  143. }
  144. template <typename ForwardIt>
  145. constexpr ForwardIt min_element(ForwardIt first, ForwardIt last) {
  146. if (first == last)
  147. return last;
  148. ForwardIt smallest = first;
  149. ++first;
  150. for (; first != last; ++first)
  151. if (*first < *smallest)
  152. smallest = first;
  153. return smallest;
  154. }
  155. } BOOST_HANA_NAMESPACE_END
  156. #endif // !BOOST_HANA_DETAIL_ALGORITHM_HPP