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.

530 lines
20KB

  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2014-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_VIEW_INTERFACE_HPP
  14. #define RANGES_V3_VIEW_INTERFACE_HPP
  15. #include <iosfwd>
  16. #include <meta/meta.hpp>
  17. #include <concepts/concepts.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/iterator/common_iterator.hpp>
  20. #include <range/v3/iterator/operations.hpp>
  21. #include <range/v3/range/access.hpp>
  22. #include <range/v3/range/concepts.hpp>
  23. #include <range/v3/range/conversion.hpp>
  24. #include <range/v3/range/primitives.hpp>
  25. #include <range/v3/range/traits.hpp>
  26. #if defined(RANGES_WORKAROUND_GCC_91525)
  27. #define CPP_template_gcc_workaround CPP_template_sfinae
  28. #else
  29. #define CPP_template_gcc_workaround CPP_template
  30. #endif
  31. namespace ranges
  32. {
  33. /// \cond
  34. namespace detail
  35. {
  36. template<typename From, typename To = From>
  37. struct slice_bounds
  38. {
  39. From from;
  40. To to;
  41. template<typename F, typename T>
  42. constexpr CPP_ctor(slice_bounds)(F f, T t)( //
  43. requires convertible_to<F, From> && convertible_to<T, To>)
  44. : from(static_cast<From>(f))
  45. , to(static_cast<To>(t))
  46. {}
  47. };
  48. template<typename Int>
  49. struct from_end_
  50. {
  51. Int dist_;
  52. constexpr explicit from_end_(Int dist)
  53. : dist_(dist)
  54. {}
  55. CPP_template(typename Other)( //
  56. requires integer_like_<Other> && explicitly_convertible_to<Other, Int>) //
  57. constexpr
  58. operator from_end_<Other>() const
  59. {
  60. return from_end_<Other>{static_cast<Other>(dist_)};
  61. }
  62. };
  63. template<typename Rng>
  64. using from_end_of_t = from_end_<range_difference_t<Rng>>;
  65. // clang-format off
  66. CPP_def
  67. (
  68. template(typename Rng)
  69. concept can_empty_,
  70. requires (Rng &rng)
  71. (
  72. ranges::empty(rng)
  73. )
  74. );
  75. // clang-format on
  76. constexpr bool has_fixed_size_(cardinality c) noexcept
  77. {
  78. return c >= 0 || c == infinite;
  79. }
  80. template<bool>
  81. struct dependent_
  82. {
  83. template<typename T>
  84. using invoke = T;
  85. };
  86. template<typename Stream, typename Rng>
  87. Stream & print_rng_(Stream & sout, Rng & rng)
  88. {
  89. sout << '[';
  90. auto it = ranges::begin(rng);
  91. auto const e = ranges::end(rng);
  92. if(it != e)
  93. {
  94. for(;;)
  95. {
  96. sout << *it;
  97. if(++it == e)
  98. break;
  99. sout << ',';
  100. }
  101. }
  102. sout << ']';
  103. return sout;
  104. }
  105. } // namespace detail
  106. /// \endcond
  107. /// \addtogroup group-views
  108. /// @{
  109. template<typename Derived, cardinality Cardinality /* = finite*/>
  110. struct view_interface : basic_view<Cardinality>
  111. {
  112. protected:
  113. template<bool B>
  114. using D = meta::invoke<detail::dependent_<B>, Derived>;
  115. constexpr Derived & derived() noexcept
  116. {
  117. CPP_assert(derived_from<Derived, view_interface>);
  118. return static_cast<Derived &>(*this);
  119. }
  120. /// \overload
  121. constexpr Derived const & derived() const noexcept
  122. {
  123. CPP_assert(derived_from<Derived, view_interface>);
  124. return static_cast<Derived const &>(*this);
  125. }
  126. ~view_interface() = default;
  127. public:
  128. view_interface() = default;
  129. view_interface(view_interface &&) = default;
  130. view_interface(view_interface const &) = default;
  131. view_interface & operator=(view_interface &&) = default;
  132. view_interface & operator=(view_interface const &) = default;
  133. // A few ways of testing whether a range can be empty:
  134. CPP_member
  135. constexpr auto empty() const noexcept -> CPP_ret(bool)( //
  136. requires(detail::has_fixed_size_(Cardinality)))
  137. {
  138. return Cardinality == 0;
  139. }
  140. /// \overload
  141. template<bool True = true>
  142. constexpr auto empty() noexcept(noexcept(
  143. bool(ranges::size(std::declval<D<True> &>()) == 0))) -> CPP_ret(bool)( //
  144. requires True && (Cardinality < 0) && (Cardinality != infinite) &&
  145. (!forward_range<D<True>>)&&sized_range<D<True>>)
  146. {
  147. return ranges::size(derived()) == 0;
  148. }
  149. /// \overload
  150. template<bool True = true>
  151. constexpr auto empty() const
  152. noexcept(noexcept(bool(ranges::size(std::declval<D<True> const &>()) == 0)))
  153. -> CPP_ret(bool)( //
  154. requires True && (Cardinality < 0) && (Cardinality != infinite) &&
  155. (!forward_range<D<True> const>)&&sized_range<D<True> const>)
  156. {
  157. return ranges::size(derived()) == 0;
  158. }
  159. /// \overload
  160. template<bool True = true>
  161. constexpr auto empty() noexcept(
  162. noexcept(bool(ranges::begin(std::declval<D<True> &>()) ==
  163. ranges::end(std::declval<D<True> &>())))) -> CPP_ret(bool)( //
  164. requires True && (!detail::has_fixed_size_(Cardinality)) &&
  165. forward_range<D<True>>)
  166. {
  167. return bool(ranges::begin(derived()) == ranges::end(derived()));
  168. }
  169. /// \overload
  170. template<bool True = true>
  171. constexpr auto empty() const
  172. noexcept(noexcept(bool(ranges::begin(std::declval<D<True> const &>()) ==
  173. ranges::end(std::declval<D<True> const &>()))))
  174. -> CPP_ret(bool)( //
  175. requires True && (!detail::has_fixed_size_(Cardinality)) &&
  176. forward_range<D<True> const>)
  177. {
  178. return bool(ranges::begin(derived()) == ranges::end(derived()));
  179. }
  180. CPP_template_gcc_workaround(bool True = true)( //
  181. requires True && detail::can_empty_<D<True>>) // clang-format off
  182. constexpr explicit operator bool()
  183. noexcept(noexcept(ranges::empty(std::declval<D<True> &>())))
  184. {
  185. return !ranges::empty(derived());
  186. }
  187. // clang-format on
  188. /// \overload
  189. CPP_template_gcc_workaround(bool True = true)( //
  190. requires True && detail::can_empty_<D<True> const>) // clang-format off
  191. constexpr explicit operator bool() const
  192. noexcept(noexcept(ranges::empty(std::declval<D<True> const &>())))
  193. {
  194. return !ranges::empty(derived());
  195. }
  196. // clang-format on
  197. /// If the size of the range is known at compile-time and finite,
  198. /// return it.
  199. template<bool True = true, int = 42>
  200. static constexpr auto size() noexcept -> CPP_ret(std::size_t)( //
  201. requires True && (Cardinality >= 0))
  202. {
  203. return static_cast<std::size_t>(Cardinality);
  204. }
  205. /// If `sized_sentinel_for<sentinel_t<Derived>, iterator_t<Derived>>` is
  206. /// satisfied, and if `Derived` is a `forward_range`, then return
  207. /// `end - begin` cast to an unsigned integer.
  208. template<bool True = true>
  209. constexpr auto size() -> CPP_ret(detail::iter_size_t<iterator_t<D<True>>>)( //
  210. requires True && (Cardinality < 0) &&
  211. sized_sentinel_for<sentinel_t<D<True>>, iterator_t<D<True>>> &&
  212. forward_range<D<True>>)
  213. {
  214. using size_type = detail::iter_size_t<iterator_t<D<True>>>;
  215. return static_cast<size_type>(derived().end() - derived().begin());
  216. }
  217. /// \overload
  218. template<bool True = true>
  219. constexpr auto size() const //
  220. -> CPP_ret(detail::iter_size_t<iterator_t<D<True>>>)( //
  221. requires True && (Cardinality < 0) &&
  222. sized_sentinel_for<sentinel_t<D<True> const>,
  223. iterator_t<D<True> const>> &&
  224. forward_range<D<True> const>)
  225. {
  226. using size_type = detail::iter_size_t<iterator_t<D<True>>>;
  227. return static_cast<size_type>(derived().end() - derived().begin());
  228. }
  229. /// Access the first element in a range:
  230. template<bool True = true>
  231. constexpr auto front() -> CPP_ret(range_reference_t<D<True>>)( //
  232. requires True && forward_range<D<True>>)
  233. {
  234. return *derived().begin();
  235. }
  236. /// \overload
  237. template<bool True = true>
  238. constexpr auto front() const -> CPP_ret(range_reference_t<D<True> const>)( //
  239. requires True && forward_range<D<True> const>)
  240. {
  241. return *derived().begin();
  242. }
  243. /// Access the last element in a range:
  244. template<bool True = true>
  245. constexpr auto back() -> CPP_ret(range_reference_t<D<True>>)( //
  246. requires True && common_range<D<True>> && bidirectional_range<D<True>>)
  247. {
  248. return *prev(derived().end());
  249. }
  250. /// \overload
  251. template<bool True = true>
  252. constexpr auto back() const -> CPP_ret(range_reference_t<D<True> const>)( //
  253. requires True && common_range<D<True> const> &&
  254. bidirectional_range<D<True> const>)
  255. {
  256. return *prev(derived().end());
  257. }
  258. /// Simple indexing:
  259. template<bool True = true>
  260. constexpr auto operator[](range_difference_t<D<True>> n)
  261. -> CPP_ret(range_reference_t<D<True>>)( //
  262. requires True && random_access_range<D<True>>)
  263. {
  264. return derived().begin()[n];
  265. }
  266. /// \overload
  267. template<bool True = true>
  268. constexpr auto operator[](range_difference_t<D<True>> n) const
  269. -> CPP_ret(range_reference_t<D<True> const>)( //
  270. requires True && random_access_range<D<True> const>)
  271. {
  272. return derived().begin()[n];
  273. }
  274. /// Returns a reference to the element at specified location pos, with bounds
  275. /// checking.
  276. template<bool True = true>
  277. constexpr auto at(range_difference_t<D<True>> n)
  278. -> CPP_ret(range_reference_t<D<True>>)( //
  279. requires True && random_access_range<D<True>> && sized_range<D<True>>)
  280. {
  281. using size_type = range_size_t<Derived>;
  282. if(n < 0 || size_type(n) >= ranges::size(derived()))
  283. {
  284. throw std::out_of_range("view_interface::at");
  285. }
  286. return derived().begin()[n];
  287. }
  288. /// \overload
  289. template<bool True = true>
  290. constexpr auto at(range_difference_t<D<True>> n) const
  291. -> CPP_ret(range_reference_t<D<True> const>)( //
  292. requires True && random_access_range<D<True> const> &&
  293. sized_range<D<True> const>)
  294. {
  295. using size_type = range_size_t<Derived const>;
  296. if(n < 0 || size_type(n) >= ranges::size(derived()))
  297. {
  298. throw std::out_of_range("view_interface::at");
  299. }
  300. return derived().begin()[n];
  301. }
  302. /// Python-ic slicing:
  303. // rng[{4,6}]
  304. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  305. requires True && input_range<D<True> &>) //
  306. constexpr auto
  307. operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) &
  308. {
  309. return Slice{}(derived(), offs.from, offs.to);
  310. }
  311. /// \overload
  312. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  313. requires True && input_range<D<True> const &>) //
  314. constexpr auto
  315. operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) const &
  316. {
  317. return Slice{}(derived(), offs.from, offs.to);
  318. }
  319. /// \overload
  320. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  321. requires True && input_range<D<True>>) //
  322. constexpr auto
  323. operator[](detail::slice_bounds<range_difference_t<D<True>>> offs) &&
  324. {
  325. return Slice{}(detail::move(derived()), offs.from, offs.to);
  326. }
  327. // rng[{4,end-2}]
  328. /// \overload
  329. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  330. requires True && input_range<D<True> &> && sized_range<D<True> &>) //
  331. constexpr auto
  332. operator[](detail::slice_bounds<range_difference_t<D<True>>,
  333. detail::from_end_of_t<D<True>>>
  334. offs) &
  335. {
  336. return Slice{}(derived(), offs.from, offs.to);
  337. }
  338. /// \overload
  339. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  340. requires True && input_range<D<True> const &> &&
  341. sized_range<D<True> const &>) //
  342. constexpr auto
  343. operator[](detail::slice_bounds<range_difference_t<D<True>>,
  344. detail::from_end_of_t<D<True>>>
  345. offs) const &
  346. {
  347. return Slice{}(derived(), offs.from, offs.to);
  348. }
  349. /// \overload
  350. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  351. requires True && input_range<D<True>> && sized_range<D<True>>) //
  352. constexpr auto
  353. operator[](detail::slice_bounds<range_difference_t<D<True>>,
  354. detail::from_end_of_t<D<True>>>
  355. offs) &&
  356. {
  357. return Slice{}(detail::move(derived()), offs.from, offs.to);
  358. }
  359. // rng[{end-4,end-2}]
  360. /// \overload
  361. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  362. requires True && (forward_range<D<True> &> ||
  363. (input_range<D<True> &> && sized_range<D<True> &>))) //
  364. constexpr auto
  365. operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
  366. detail::from_end_of_t<D<True>>>
  367. offs) &
  368. {
  369. return Slice{}(derived(), offs.from, offs.to);
  370. }
  371. /// \overload
  372. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  373. requires True &&
  374. (forward_range<D<True> const &> ||
  375. (input_range<D<True> const &> && sized_range<D<True> const &>))) //
  376. constexpr auto
  377. operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
  378. detail::from_end_of_t<D<True>>>
  379. offs) const &
  380. {
  381. return Slice{}(derived(), offs.from, offs.to);
  382. }
  383. /// \overload
  384. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  385. requires True &&
  386. (forward_range<D<True>> || (input_range<D<True>> && sized_range<D<True>>))) //
  387. constexpr auto
  388. operator[](detail::slice_bounds<detail::from_end_of_t<D<True>>,
  389. detail::from_end_of_t<D<True>>>
  390. offs) &&
  391. {
  392. return Slice{}(detail::move(derived()), offs.from, offs.to);
  393. }
  394. // rng[{4,end}]
  395. /// \overload
  396. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  397. requires True && input_range<D<True> &>) //
  398. constexpr auto
  399. operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) &
  400. {
  401. return Slice{}(derived(), offs.from, offs.to);
  402. }
  403. /// \overload
  404. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  405. requires True && input_range<D<True> const &>) //
  406. constexpr auto
  407. operator[](
  408. detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) const &
  409. {
  410. return Slice{}(derived(), offs.from, offs.to);
  411. }
  412. /// \overload
  413. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  414. requires True && input_range<D<True>>) //
  415. constexpr auto
  416. operator[](detail::slice_bounds<range_difference_t<D<True>>, end_fn> offs) &&
  417. {
  418. return Slice{}(detail::move(derived()), offs.from, offs.to);
  419. }
  420. // rng[{end-4,end}]
  421. /// \overload
  422. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  423. requires True && (forward_range<D<True> &> ||
  424. (input_range<D<True> &> && sized_range<D<True> &>))) //
  425. constexpr auto
  426. operator[](
  427. detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) &
  428. {
  429. return Slice{}(derived(), offs.from, offs.to);
  430. }
  431. /// \overload
  432. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  433. requires True &&
  434. (forward_range<D<True> const &> ||
  435. (input_range<D<True> const &> && sized_range<D<True> const &>))) //
  436. constexpr auto
  437. operator[](
  438. detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) const &
  439. {
  440. return Slice{}(derived(), offs.from, offs.to);
  441. }
  442. /// \overload
  443. CPP_template(bool True = true, typename Slice = views::slice_fn)( //
  444. requires True &&
  445. (forward_range<D<True>> || (input_range<D<True>> && sized_range<D<True>>))) //
  446. constexpr auto
  447. operator[](
  448. detail::slice_bounds<detail::from_end_of_t<D<True>>, end_fn> offs) &&
  449. {
  450. return Slice{}(detail::move(derived()), offs.from, offs.to);
  451. }
  452. /// \cond
  453. /// Implicit conversion to something that looks like a container.
  454. CPP_template(typename Container, bool True = true)( // clang-format off
  455. requires detail::convertible_to_container<D<True>, Container>)
  456. RANGES_DEPRECATED(
  457. "Implicit conversion from a view to a container is deprecated. "
  458. "Please use ranges::to in <range/v3/range/conversion.hpp> instead.")
  459. constexpr operator Container() // clang-format on
  460. {
  461. return ranges::to<Container>(derived());
  462. }
  463. /// \overload
  464. CPP_template(typename Container, bool True = true)( // clang-format off
  465. requires detail::convertible_to_container<D<True> const, Container>)
  466. RANGES_DEPRECATED(
  467. "Implicit conversion from a view to a container is deprecated. "
  468. "Please use ranges::to in <range/v3/range/conversion.hpp> instead.")
  469. constexpr operator Container() const // clang-format on
  470. {
  471. return ranges::to<Container>(derived());
  472. }
  473. /// \endcond
  474. private:
  475. /// \brief Print a range to an ostream
  476. template<bool True = true>
  477. friend auto operator<<(std::ostream & sout, Derived const & rng)
  478. -> CPP_broken_friend_ret(std::ostream &)( //
  479. requires True && input_range<D<True> const>)
  480. {
  481. return detail::print_rng_(sout, rng);
  482. }
  483. /// \overload
  484. template<bool True = true>
  485. friend auto operator<<(std::ostream & sout, Derived & rng)
  486. -> CPP_broken_friend_ret(std::ostream &)( //
  487. requires True && (!range<D<True> const>)&&input_range<D<True>>)
  488. {
  489. return detail::print_rng_(sout, rng);
  490. }
  491. /// \overload
  492. template<bool True = true>
  493. friend auto operator<<(std::ostream & sout, Derived && rng)
  494. -> CPP_broken_friend_ret(std::ostream &)( //
  495. requires True && (!range<D<True> const>)&&input_range<D<True>>)
  496. {
  497. return detail::print_rng_(sout, rng);
  498. }
  499. };
  500. namespace cpp20
  501. {
  502. CPP_template(typename Derived)( //
  503. requires std::is_class<Derived>::value &&
  504. same_as<Derived, meta::_t<std::remove_cv<Derived>>>) //
  505. using view_interface = ranges::view_interface<Derived, ranges::unknown>;
  506. }
  507. /// @}
  508. } // namespace ranges
  509. #endif