You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

concepts.hpp 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  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. namespace ranges
  21. {
  22. /// \cond
  23. namespace detail
  24. {
  25. template<typename T>
  26. struct movable_input_iterator
  27. {
  28. using iterator_category = std::input_iterator_tag;
  29. using value_type = T;
  30. using difference_type = std::ptrdiff_t;
  31. using pointer = T *;
  32. using reference = T &&;
  33. movable_input_iterator() = default;
  34. movable_input_iterator & operator++();
  35. movable_input_iterator operator++(int);
  36. bool operator==(movable_input_iterator const &) const;
  37. bool operator!=(movable_input_iterator const &) const;
  38. T && operator*() const;
  39. };
  40. } // namespace detail
  41. /// \endcond
  42. /// \addtogroup group-range
  43. /// @{
  44. // std::array is a semi_container, native arrays are not.
  45. // clang-format off
  46. CPP_def
  47. (
  48. template(typename T)
  49. concept semi_container,
  50. forward_range<T> && default_constructible<uncvref_t<T>> &&
  51. movable<uncvref_t<T>> &&
  52. !view_<T>
  53. );
  54. // std::vector is a container, std::array is not
  55. CPP_def
  56. (
  57. template(typename T)
  58. concept container,
  59. semi_container<T> &&
  60. constructible_from<
  61. uncvref_t<T>,
  62. detail::movable_input_iterator<range_value_t<T>>,
  63. detail::movable_input_iterator<range_value_t<T>>>
  64. );
  65. CPP_def
  66. (
  67. template(typename C)
  68. concept reservable,
  69. requires (C &c, C const &cc, range_size_t<C> s)
  70. (
  71. c.reserve(s),
  72. cc.capacity(),
  73. cc.max_size(),
  74. concepts::requires_<same_as<decltype(cc.capacity()), range_size_t<C>>>,
  75. concepts::requires_<same_as<decltype(cc.max_size()), range_size_t<C>>>
  76. ) &&
  77. container<C> && sized_range<C>
  78. );
  79. CPP_def
  80. (
  81. template(typename C, typename I)
  82. concept reservable_with_assign,
  83. requires (C &c, I i)
  84. (
  85. c.assign(i, i)
  86. ) &&
  87. reservable<C> && input_iterator<I>
  88. );
  89. CPP_def
  90. (
  91. template(typename C)
  92. concept random_access_reservable,
  93. reservable<C> && random_access_range<C>
  94. );
  95. // clang-format on
  96. /// \cond
  97. namespace detail
  98. {
  99. template<typename T>
  100. auto is_lvalue_container_like(T &) noexcept -> CPP_ret(std::true_type)( //
  101. requires container<T>)
  102. {
  103. return {};
  104. }
  105. template<typename T>
  106. auto is_lvalue_container_like(reference_wrapper<T>) noexcept
  107. -> CPP_ret(meta::not_<std::is_rvalue_reference<T>>)( //
  108. requires container<T>)
  109. {
  110. return {};
  111. }
  112. template<typename T>
  113. auto is_lvalue_container_like(std::reference_wrapper<T>) noexcept
  114. -> CPP_ret(std::true_type)( //
  115. requires container<T>)
  116. {
  117. return {};
  118. }
  119. template<typename T>
  120. auto is_lvalue_container_like(ref_view<T>) noexcept -> CPP_ret(std::true_type)( //
  121. requires container<T>)
  122. {
  123. return {};
  124. }
  125. template<typename T>
  126. using is_lvalue_container_like_t =
  127. decltype(detail::is_lvalue_container_like(std::declval<T>()));
  128. } // namespace detail
  129. /// \endcond
  130. // clang-format off
  131. CPP_def
  132. (
  133. template(typename T)
  134. concept lvalue_container_like,
  135. implicitly_convertible_to<detail::is_lvalue_container_like_t<T>,
  136. std::true_type> &&
  137. forward_range<T>
  138. );
  139. // clang-format on
  140. /// @}
  141. } // namespace ranges
  142. #endif