concepts.hpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_ACTION_CONCEPTS_HPP
  14. #define RANGES_V3_ACTION_CONCEPTS_HPP
  15. #include <utility>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/range/concepts.hpp>
  19. #include <range/v3/range/traits.hpp>
  20. #include <range/v3/detail/prologue.hpp>
  21. namespace ranges
  22. {
  23. /// \cond
  24. namespace detail
  25. {
  26. template<typename T>
  27. struct movable_input_iterator
  28. {
  29. using iterator_category = std::input_iterator_tag;
  30. using value_type = T;
  31. using difference_type = std::ptrdiff_t;
  32. using pointer = T *;
  33. using reference = T &&;
  34. movable_input_iterator() = default;
  35. movable_input_iterator & operator++();
  36. movable_input_iterator operator++(int);
  37. bool operator==(movable_input_iterator const &) const;
  38. bool operator!=(movable_input_iterator const &) const;
  39. T && operator*() const;
  40. };
  41. } // namespace detail
  42. /// \endcond
  43. /// \addtogroup group-range
  44. /// @{
  45. // clang-format off
  46. /// \concept semi_container
  47. /// \brief The \c semi_container concept
  48. /// \c std::array is a \c semi_container, native arrays are not.
  49. template<typename T>
  50. CPP_concept semi_container =
  51. forward_range<T> && default_constructible<uncvref_t<T>> &&
  52. movable<uncvref_t<T>> &&
  53. !view_<T>;
  54. /// \concept container_
  55. /// \brief The \c container_ concept
  56. /// \c std::vector is a container, \c std::array is not
  57. template(typename T)(
  58. concept (container_)(T),
  59. constructible_from<
  60. uncvref_t<T>,
  61. detail::movable_input_iterator<range_value_t<T>>,
  62. detail::movable_input_iterator<range_value_t<T>>>
  63. );
  64. /// \concept container
  65. /// \brief The \c container concept
  66. template<typename T>
  67. CPP_concept container =
  68. semi_container<T> &&
  69. CPP_concept_ref(ranges::container_, T);
  70. /// \concept reservable_
  71. /// \brief The \c reservable_ concept
  72. template<typename C>
  73. CPP_requires(reservable_,
  74. requires(C & c, C const & cc) //
  75. (
  76. c.reserve(ranges::size(c)),
  77. cc.capacity(),
  78. cc.max_size(),
  79. concepts::requires_<same_as<decltype(cc.capacity()),
  80. decltype(ranges::size(c))>>,
  81. concepts::requires_<same_as<decltype(cc.max_size()),
  82. decltype(ranges::size(c))>>
  83. ));
  84. /// \concept reservable
  85. /// \brief The \c reservable concept
  86. template<typename C>
  87. CPP_concept reservable =
  88. container<C> && sized_range<C> && CPP_requires_ref(ranges::reservable_, C);
  89. /// \concept reservable_with_assign_
  90. /// \brief The \c reservable_with_assign_ concept
  91. template<typename C, typename I>
  92. CPP_requires(reservable_with_assign_,
  93. requires(C & c, I i) //
  94. (
  95. c.assign(i, i)
  96. ));
  97. /// \concept reservable_with_assign
  98. /// \brief The \c reservable_with_assign concept
  99. template<typename C, typename I>
  100. CPP_concept reservable_with_assign =
  101. reservable<C> && //
  102. input_iterator<I> && //
  103. CPP_requires_ref(ranges::reservable_with_assign_, C, I);
  104. /// \concept random_access_reservable
  105. /// \brief The \c random_access_reservable concept
  106. template<typename C>
  107. CPP_concept random_access_reservable =
  108. reservable<C> && random_access_range<C>;
  109. // clang-format on
  110. /// \cond
  111. namespace detail
  112. {
  113. template(typename T)(
  114. requires container<T>)
  115. std::true_type is_lvalue_container_like(T &) noexcept
  116. {
  117. return {};
  118. }
  119. template(typename T)(
  120. requires container<T>)
  121. meta::not_<std::is_rvalue_reference<T>> //
  122. is_lvalue_container_like(reference_wrapper<T>) noexcept
  123. {
  124. return {};
  125. }
  126. template(typename T)(
  127. requires container<T>)
  128. std::true_type is_lvalue_container_like(std::reference_wrapper<T>) noexcept
  129. {
  130. return {};
  131. }
  132. template(typename T)(
  133. requires container<T>)
  134. std::true_type is_lvalue_container_like(ref_view<T>) noexcept
  135. {
  136. return {};
  137. }
  138. template<typename T>
  139. using is_lvalue_container_like_t =
  140. decltype(detail::is_lvalue_container_like(std::declval<T>()));
  141. } // namespace detail
  142. /// \endcond
  143. // clang-format off
  144. /// \concept lvalue_container_like_
  145. /// \brief The \c lvalue_container_like_ concept
  146. template(typename T)(
  147. concept (lvalue_container_like_)(T),
  148. implicitly_convertible_to<detail::is_lvalue_container_like_t<T>, std::true_type>
  149. );
  150. /// \concept lvalue_container_like
  151. /// \brief The \c lvalue_container_like concept
  152. template<typename T>
  153. CPP_concept lvalue_container_like =
  154. forward_range<T> &&
  155. CPP_concept_ref(ranges::lvalue_container_like_, T);
  156. // clang-format on
  157. /// @}
  158. } // namespace ranges
  159. #include <range/v3/detail/epilogue.hpp>
  160. #endif