Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

427 linhas
11KB

  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_RANGE_CONCEPTS_HPP
  14. #define RANGES_V3_RANGE_CONCEPTS_HPP
  15. #include <initializer_list>
  16. #include <type_traits>
  17. #include <utility>
  18. #include <meta/meta.hpp>
  19. #include <concepts/concepts.hpp>
  20. #include <range/v3/range_fwd.hpp>
  21. #include <range/v3/functional/comparisons.hpp>
  22. #include <range/v3/iterator/concepts.hpp>
  23. #include <range/v3/iterator/traits.hpp>
  24. #include <range/v3/range/access.hpp>
  25. #include <range/v3/range/primitives.hpp>
  26. #include <range/v3/range/traits.hpp>
  27. #ifndef RANGES_NO_STD_FORWARD_DECLARATIONS
  28. // Non-portable forward declarations of standard containers
  29. RANGES_BEGIN_NAMESPACE_STD
  30. RANGES_BEGIN_NAMESPACE_CONTAINER
  31. template<typename Key,
  32. typename Compare /*= less<Key>*/,
  33. typename Alloc /*= allocator<Key>*/>
  34. class set;
  35. template<typename Key,
  36. typename Compare /*= less<Key>*/,
  37. typename Alloc /*= allocator<Key>*/>
  38. class multiset;
  39. template<typename Key,
  40. typename Hash /*= hash<Key>*/,
  41. typename Pred /*= equal_to<Key>*/,
  42. typename Alloc /*= allocator<Key>*/>
  43. class unordered_set;
  44. template<typename Key,
  45. typename Hash /*= hash<Key>*/,
  46. typename Pred /*= equal_to<Key>*/,
  47. typename Alloc /*= allocator<Key>*/>
  48. class unordered_multiset;
  49. RANGES_END_NAMESPACE_CONTAINER
  50. RANGES_END_NAMESPACE_STD
  51. #else
  52. #include <set>
  53. #include <unordered_set>
  54. #endif
  55. namespace ranges
  56. {
  57. /// \addtogroup group-range
  58. /// @{
  59. ///
  60. /// Range concepts below
  61. ///
  62. /// \cond
  63. // clang-format off
  64. CPP_def
  65. (
  66. template(typename T)
  67. concept range_impl_,
  68. requires(T &&t) (
  69. ranges::begin(static_cast<T &&>(t)), // not necessarily equality-preserving
  70. ranges::end(static_cast<T &&>(t))
  71. )
  72. );
  73. /// \endcond
  74. CPP_def
  75. (
  76. template(typename T)
  77. concept range,
  78. range_impl_<T &>
  79. );
  80. /// \cond
  81. CPP_def
  82. (
  83. template(typename T)
  84. concept forwarding_range_,
  85. range<T> && range_impl_<T>
  86. );
  87. /// \endcond
  88. CPP_def
  89. (
  90. template(typename T, typename V)
  91. concept output_range,
  92. range<T> && output_iterator<iterator_t<T>, V>
  93. );
  94. /// \cond
  95. // Needed to work around a bug in GCC
  96. CPP_def
  97. (
  98. template(typename T)
  99. concept input_range_,
  100. input_iterator<iterator_t<T>>
  101. );
  102. /// \endcond
  103. CPP_def
  104. (
  105. template(typename T)
  106. concept input_range,
  107. range<T> && input_range_<T>
  108. );
  109. /// \cond
  110. // Needed to work around a bug in GCC
  111. CPP_def
  112. (
  113. template(typename T)
  114. concept forward_range_,
  115. forward_iterator<iterator_t<T>>
  116. );
  117. /// \endcond
  118. CPP_def
  119. (
  120. template(typename T)
  121. concept forward_range,
  122. input_range<T> && forward_range_<T>
  123. );
  124. /// \cond
  125. // Needed to work around a bug in GCC
  126. CPP_def
  127. (
  128. template(typename T)
  129. concept bidirectional_range_,
  130. bidirectional_iterator<iterator_t<T>>
  131. );
  132. /// \endcond
  133. CPP_def
  134. (
  135. template(typename T)
  136. concept bidirectional_range,
  137. forward_range<T> && bidirectional_range_<T>
  138. );
  139. /// \cond
  140. // Needed to work around a bug in GCC
  141. CPP_def
  142. (
  143. template(typename T)
  144. concept random_access_range_,
  145. random_access_iterator<iterator_t<T>>
  146. );
  147. /// \endcond
  148. CPP_def
  149. (
  150. template(typename T)
  151. concept random_access_range,
  152. bidirectional_range<T> && random_access_range_<T>
  153. );
  154. // clang-format on
  155. /// \cond
  156. namespace detail
  157. {
  158. template<typename Rng>
  159. using data_t = decltype(ranges::data(std::declval<Rng &>()));
  160. template<typename Rng>
  161. using element_t = meta::_t<std::remove_pointer<data_t<Rng>>>;
  162. } // namespace detail
  163. /// \endcond
  164. /// \cond
  165. // Needed to work around a bug in GCC
  166. // clang-format off
  167. CPP_def
  168. (
  169. template(typename T)
  170. concept contiguous_range_,
  171. contiguous_iterator<iterator_t<T>> &&
  172. same_as<detail::data_t<T>, meta::_t<std::add_pointer<iter_reference_t<iterator_t<T>>>>>
  173. );
  174. /// \endcond
  175. CPP_def
  176. (
  177. template(typename T)
  178. concept contiguous_range,
  179. random_access_range<T> && contiguous_range_<T>
  180. );
  181. /// \cond
  182. // Needed to work around a bug in GCC
  183. CPP_def
  184. (
  185. template(typename T)
  186. concept common_range_,
  187. same_as<iterator_t<T>, sentinel_t<T>>
  188. );
  189. /// \endcond
  190. CPP_def
  191. (
  192. template(typename T)
  193. concept common_range,
  194. range<T> && common_range_<T>
  195. );
  196. /// \cond
  197. CPP_def
  198. (
  199. template(typename T)
  200. concept bounded_range,
  201. common_range<T>
  202. );
  203. /// \endcond
  204. CPP_def
  205. (
  206. template(typename T)
  207. concept sized_range,
  208. requires (T &t)
  209. (
  210. ranges::size(t)
  211. ) &&
  212. range<T> &&
  213. detail::integer_like_<range_size_t<T>> &&
  214. !disable_sized_range<uncvref_t<T>>
  215. );
  216. // clang-format on
  217. /// \cond
  218. namespace detail
  219. {
  220. struct enable_view_helper_
  221. {
  222. bool result_;
  223. template<typename T>
  224. static constexpr auto test(T const *) -> CPP_ret(bool)( //
  225. requires range<T> && range<T const>)
  226. {
  227. return RANGES_IS_SAME(iter_reference_t<iterator_t<T>>,
  228. iter_reference_t<iterator_t<T const>>);
  229. }
  230. static constexpr auto test(void const *) -> bool
  231. {
  232. return true;
  233. }
  234. template<typename T>
  235. constexpr enable_view_helper_(T const * p)
  236. : result_(enable_view_helper_::test(p))
  237. {}
  238. };
  239. constexpr bool enable_view_impl_(...)
  240. {
  241. return false;
  242. }
  243. constexpr bool enable_view_impl_(view_base const *)
  244. {
  245. return true;
  246. }
  247. constexpr bool enable_view_impl_(enable_view_helper_ ev)
  248. {
  249. return ev.result_;
  250. }
  251. template<typename T>
  252. constexpr bool enable_view_impl_(std::initializer_list<T> const *)
  253. {
  254. return false;
  255. }
  256. template<typename Key, typename Compare, typename Alloc>
  257. constexpr bool enable_view_impl_(std::set<Key, Compare, Alloc> const *)
  258. {
  259. return false;
  260. }
  261. template<typename Key, typename Compare, typename Alloc>
  262. constexpr bool enable_view_impl_(std::multiset<Key, Compare, Alloc> const *)
  263. {
  264. return false;
  265. }
  266. template<typename Key, typename Hash, typename Pred, typename Alloc>
  267. constexpr bool enable_view_impl_(
  268. std::unordered_set<Key, Hash, Pred, Alloc> const *)
  269. {
  270. return false;
  271. }
  272. template<typename Key, typename Hash, typename Pred, typename Alloc>
  273. constexpr bool enable_view_impl_(
  274. std::unordered_multiset<Key, Hash, Pred, Alloc> const *)
  275. {
  276. return false;
  277. }
  278. // BUGBUG TODO
  279. // template<typename BidiIter, typename Alloc>
  280. // constexpr bool enable_view_impl_(std::match_results<BidiIter, Alloc> const *)
  281. // {
  282. // return false;
  283. // }
  284. template<typename T>
  285. constexpr T const * nullptr_(int)
  286. {
  287. return nullptr;
  288. }
  289. template<typename T>
  290. constexpr int nullptr_(long)
  291. {
  292. return 0;
  293. }
  294. } // namespace detail
  295. /// \endcond
  296. // Specialize this if the default is wrong.
  297. template<typename T>
  298. RANGES_INLINE_VAR constexpr bool enable_view =
  299. detail::enable_view_impl_(detail::nullptr_<T>(0));
  300. ///
  301. /// View concepts below
  302. ///
  303. // clang-format off
  304. CPP_def
  305. (
  306. template(typename T)
  307. concept view_,
  308. range<T> &&
  309. semiregular<T> &&
  310. enable_view<T>
  311. );
  312. CPP_def
  313. (
  314. template(typename T)
  315. concept viewable_range,
  316. range<T> &&
  317. (forwarding_range_<T> || view_<detail::decay_t<T>>)
  318. );
  319. // clang-format on
  320. ////////////////////////////////////////////////////////////////////////////////////////////
  321. // range_tag
  322. using range_tag = ::concepts::tag<range_concept>;
  323. using input_range_tag = ::concepts::tag<input_range_concept, range_tag>;
  324. using forward_range_tag = ::concepts::tag<forward_range_concept, input_range_tag>;
  325. using bidirectional_range_tag =
  326. ::concepts::tag<bidirectional_range_concept, forward_range_tag>;
  327. using random_access_range_tag =
  328. ::concepts::tag<random_access_range_concept, bidirectional_range_tag>;
  329. using contiguous_range_tag =
  330. ::concepts::tag<contiguous_range_concept, random_access_range_tag>;
  331. template<typename T>
  332. using range_tag_of = ::concepts::tag_of<
  333. meta::list<contiguous_range_concept, random_access_range_concept,
  334. bidirectional_range_concept, forward_range_concept,
  335. input_range_concept, range_concept>,
  336. T>;
  337. ////////////////////////////////////////////////////////////////////////////////////////////
  338. // common_range_tag_of
  339. using common_range_tag = ::concepts::tag<common_range_concept, range_tag>;
  340. template<typename T>
  341. using common_range_tag_of =
  342. ::concepts::tag_of<meta::list<common_range_concept, range_concept>, T>;
  343. ////////////////////////////////////////////////////////////////////////////////////////////
  344. // sized_range_concept
  345. using sized_range_tag = ::concepts::tag<sized_range_concept, range_tag>;
  346. template<typename T>
  347. using sized_range_tag_of =
  348. ::concepts::tag_of<meta::list<sized_range_concept, range_concept>, T>;
  349. /// \cond
  350. namespace view_detail_
  351. {
  352. // clang-format off
  353. CPP_def
  354. (
  355. template(typename T)
  356. concept view,
  357. ranges::view_<T>
  358. );
  359. // clang-format on
  360. } // namespace view_detail_
  361. /// \endcond
  362. namespace cpp20
  363. {
  364. using ranges::bidirectional_range;
  365. using ranges::common_range;
  366. using ranges::contiguous_range;
  367. using ranges::enable_view;
  368. using ranges::forward_range;
  369. using ranges::input_range;
  370. using ranges::output_range;
  371. using ranges::random_access_range;
  372. using ranges::range;
  373. using ranges::sized_range;
  374. using ranges::viewable_range;
  375. using ranges::view_detail_::view;
  376. } // namespace cpp20
  377. /// @}
  378. } // namespace ranges
  379. #endif