xiterable.hpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTENSOR_ITERABLE_HPP
  10. #define XTENSOR_ITERABLE_HPP
  11. #include "xiterator.hpp"
  12. namespace xt
  13. {
  14. /*******************
  15. * xconst_iterable *
  16. *******************/
  17. template <class D>
  18. struct xiterable_inner_types;
  19. /**
  20. * @class xconst_iterable
  21. * @brief Base class for multidimensional iterable constant expressions
  22. *
  23. * The xconst_iterable class defines the interface for multidimensional
  24. * constant expressions that can be iterated.
  25. *
  26. * @tparam D The derived type, i.e. the inheriting class for which xconst_iterable
  27. * provides the interface.
  28. */
  29. template <class D>
  30. class xconst_iterable
  31. {
  32. public:
  33. using derived_type = D;
  34. using iterable_types = xiterable_inner_types<D>;
  35. using inner_shape_type = typename iterable_types::inner_shape_type;
  36. using stepper = typename iterable_types::stepper;
  37. using const_stepper = typename iterable_types::const_stepper;
  38. template <layout_type L>
  39. using layout_iterator = xiterator<stepper, inner_shape_type*, L>;
  40. template <layout_type L>
  41. using const_layout_iterator = xiterator<const_stepper, inner_shape_type*, L>;
  42. template <layout_type L>
  43. using reverse_layout_iterator = std::reverse_iterator<layout_iterator<L>>;
  44. template <layout_type L>
  45. using const_reverse_layout_iterator = std::reverse_iterator<const_layout_iterator<L>>;
  46. using linear_iterator = layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  47. using const_linear_iterator = const_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  48. using reverse_linear_iterator = reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  49. using const_reverse_linear_iterator = const_reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  50. template <class S, layout_type L>
  51. using broadcast_iterator = xiterator<stepper, S, L>;
  52. template <class S, layout_type L>
  53. using const_broadcast_iterator = xiterator<const_stepper, S, L>;
  54. template <class S, layout_type L>
  55. using reverse_broadcast_iterator = std::reverse_iterator<broadcast_iterator<S, L>>;
  56. template <class S, layout_type L>
  57. using const_reverse_broadcast_iterator = std::reverse_iterator<const_broadcast_iterator<S, L>>;
  58. using iterator = layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  59. using const_iterator = const_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  60. using reverse_iterator = reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  61. using const_reverse_iterator = const_reverse_layout_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  62. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  63. const_layout_iterator<L> begin() const noexcept;
  64. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  65. const_layout_iterator<L> end() const noexcept;
  66. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  67. const_layout_iterator<L> cbegin() const noexcept;
  68. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  69. const_layout_iterator<L> cend() const noexcept;
  70. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  71. const_reverse_layout_iterator<L> rbegin() const noexcept;
  72. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  73. const_reverse_layout_iterator<L> rend() const noexcept;
  74. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  75. const_reverse_layout_iterator<L> crbegin() const noexcept;
  76. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  77. const_reverse_layout_iterator<L> crend() const noexcept;
  78. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  79. const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
  80. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  81. const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
  82. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  83. const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
  84. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  85. const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
  86. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  87. const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
  88. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  89. const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
  90. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  91. const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
  92. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  93. const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
  94. protected:
  95. const inner_shape_type& get_shape() const;
  96. private:
  97. template <layout_type L>
  98. const_layout_iterator<L> get_cbegin(bool end_index) const noexcept;
  99. template <layout_type L>
  100. const_layout_iterator<L> get_cend(bool end_index) const noexcept;
  101. template <layout_type L, class S>
  102. const_broadcast_iterator<S, L> get_cbegin(const S& shape, bool end_index) const noexcept;
  103. template <layout_type L, class S>
  104. const_broadcast_iterator<S, L> get_cend(const S& shape, bool end_index) const noexcept;
  105. template <class S>
  106. const_stepper get_stepper_begin(const S& shape) const noexcept;
  107. template <class S>
  108. const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept;
  109. const derived_type& derived_cast() const;
  110. };
  111. /*************
  112. * xiterable *
  113. *************/
  114. /**
  115. * @class xiterable
  116. * @brief Base class for multidimensional iterable expressions
  117. *
  118. * The xiterable class defines the interface for multidimensional
  119. * expressions that can be iterated.
  120. *
  121. * @tparam D The derived type, i.e. the inheriting class for which xiterable
  122. * provides the interface.
  123. */
  124. template <class D>
  125. class xiterable : public xconst_iterable<D>
  126. {
  127. public:
  128. using derived_type = D;
  129. using base_type = xconst_iterable<D>;
  130. using inner_shape_type = typename base_type::inner_shape_type;
  131. using stepper = typename base_type::stepper;
  132. using const_stepper = typename base_type::const_stepper;
  133. using linear_iterator = typename base_type::linear_iterator;
  134. using reverse_linear_iterator = typename base_type::reverse_linear_iterator;
  135. template <layout_type L>
  136. using layout_iterator = typename base_type::template layout_iterator<L>;
  137. template <layout_type L>
  138. using const_layout_iterator = typename base_type::template const_layout_iterator<L>;
  139. template <layout_type L>
  140. using reverse_layout_iterator = typename base_type::template reverse_layout_iterator<L>;
  141. template <layout_type L>
  142. using const_reverse_layout_iterator = typename base_type::template const_reverse_layout_iterator<L>;
  143. template <class S, layout_type L>
  144. using broadcast_iterator = typename base_type::template broadcast_iterator<S, L>;
  145. template <class S, layout_type L>
  146. using const_broadcast_iterator = typename base_type::template const_broadcast_iterator<S, L>;
  147. template <class S, layout_type L>
  148. using reverse_broadcast_iterator = typename base_type::template reverse_broadcast_iterator<S, L>;
  149. template <class S, layout_type L>
  150. using const_reverse_broadcast_iterator = typename base_type::template const_reverse_broadcast_iterator<S, L>;
  151. using iterator = typename base_type::iterator;
  152. using const_iterator = typename base_type::const_iterator;
  153. using reverse_iterator = typename base_type::reverse_iterator;
  154. using const_reverse_iterator = typename base_type::const_reverse_iterator;
  155. using base_type::begin;
  156. using base_type::end;
  157. using base_type::rbegin;
  158. using base_type::rend;
  159. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  160. layout_iterator<L> begin() noexcept;
  161. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  162. layout_iterator<L> end() noexcept;
  163. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  164. reverse_layout_iterator<L> rbegin() noexcept;
  165. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  166. reverse_layout_iterator<L> rend() noexcept;
  167. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  168. broadcast_iterator<S, L> begin(const S& shape) noexcept;
  169. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  170. broadcast_iterator<S, L> end(const S& shape) noexcept;
  171. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  172. reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
  173. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  174. reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
  175. private:
  176. template <layout_type L>
  177. layout_iterator<L> get_begin(bool end_index) noexcept;
  178. template <layout_type L>
  179. layout_iterator<L> get_end(bool end_index) noexcept;
  180. template <layout_type L, class S>
  181. broadcast_iterator<S, L> get_begin(const S& shape, bool end_index) noexcept;
  182. template <layout_type L, class S>
  183. broadcast_iterator<S, L> get_end(const S& shape, bool end_index) noexcept;
  184. template <class S>
  185. stepper get_stepper_begin(const S& shape) noexcept;
  186. template <class S>
  187. stepper get_stepper_end(const S& shape, layout_type l) noexcept;
  188. template <class S>
  189. const_stepper get_stepper_begin(const S& shape) const noexcept;
  190. template <class S>
  191. const_stepper get_stepper_end(const S& shape, layout_type l) const noexcept;
  192. derived_type& derived_cast();
  193. };
  194. /************************
  195. * xcontiguous_iterable *
  196. ************************/
  197. template <class D>
  198. struct xcontainer_inner_types;
  199. namespace detail
  200. {
  201. template <class T, bool is_const>
  202. struct get_storage_iterator;
  203. template <class T>
  204. struct get_storage_iterator<T, true>
  205. {
  206. using iterator = typename T::const_iterator;
  207. using const_iterator = typename T::const_iterator;
  208. using reverse_iterator = typename T::const_reverse_iterator;
  209. using const_reverse_iterator = typename T::const_reverse_iterator;
  210. };
  211. template <class T>
  212. struct get_storage_iterator<T, false>
  213. {
  214. using iterator = typename T::iterator;
  215. using const_iterator = typename T::const_iterator;
  216. using reverse_iterator = typename T::reverse_iterator;
  217. using const_reverse_iterator = typename T::const_reverse_iterator;
  218. };
  219. template <class D, bool has_storage_type>
  220. struct linear_iterator_traits_impl;
  221. template <class D>
  222. struct linear_iterator_traits_impl<D, true>
  223. {
  224. using inner_types = xcontainer_inner_types<D>;
  225. using storage_type = typename inner_types::storage_type;
  226. using iterator_type = get_storage_iterator<storage_type, std::is_const<storage_type>::value>;
  227. using linear_iterator = typename iterator_type::iterator;
  228. using const_linear_iterator = typename iterator_type::const_iterator;
  229. using reverse_linear_iterator = typename iterator_type::reverse_iterator;
  230. using const_reverse_linear_iterator = typename iterator_type::const_reverse_iterator;
  231. };
  232. template <class D>
  233. struct linear_iterator_traits_impl<D, false>
  234. {
  235. using inner_types = xcontainer_inner_types<D>;
  236. using xexpression_type = typename inner_types::xexpression_type;
  237. using linear_iterator = typename xexpression_type::linear_iterator;
  238. using const_linear_iterator = typename xexpression_type::const_linear_iterator;
  239. using reverse_linear_iterator = typename xexpression_type::reverse_linear_iterator;
  240. using const_reverse_linear_iterator = typename xexpression_type::const_reverse_linear_iterator;
  241. };
  242. template <class D>
  243. using linear_iterator_traits = linear_iterator_traits_impl<D, has_storage_type<D>::value>;
  244. }
  245. /**
  246. * @class xcontiguous_iterable
  247. * @brief Base class for multidimensional iterable expressions with
  248. * contiguous storage
  249. *
  250. * The xcontiguous_iterable class defines the interface for multidimensional
  251. * expressions with contiguous that can be iterated.
  252. *
  253. * @tparam D The derived type, i.e. the inheriting class for which xcontiguous_iterable
  254. * provides the interface.
  255. */
  256. template <class D>
  257. class xcontiguous_iterable : private xiterable<D>
  258. {
  259. public:
  260. using derived_type = D;
  261. using inner_types = xcontainer_inner_types<D>;
  262. using iterable_base = xiterable<D>;
  263. using stepper = typename iterable_base::stepper;
  264. using const_stepper = typename iterable_base::const_stepper;
  265. static constexpr layout_type static_layout = inner_types::layout;
  266. #if defined(_MSC_VER) && _MSC_VER >= 1910
  267. // Workaround for compiler bug in Visual Studio 2017 with respect to alias templates with non-type
  268. // parameters.
  269. template <layout_type L>
  270. using layout_iterator = xiterator<typename iterable_base::stepper, typename iterable_base::inner_shape_type*, L>;
  271. template <layout_type L>
  272. using const_layout_iterator = xiterator<
  273. typename iterable_base::const_stepper,
  274. typename iterable_base::inner_shape_type*,
  275. L>;
  276. template <layout_type L>
  277. using reverse_layout_iterator = std::reverse_iterator<layout_iterator<L>>;
  278. template <layout_type L>
  279. using const_reverse_layout_iterator = std::reverse_iterator<const_layout_iterator<L>>;
  280. #else
  281. template <layout_type L>
  282. using layout_iterator = typename iterable_base::template layout_iterator<L>;
  283. template <layout_type L>
  284. using const_layout_iterator = typename iterable_base::template const_layout_iterator<L>;
  285. template <layout_type L>
  286. using reverse_layout_iterator = typename iterable_base::template reverse_layout_iterator<L>;
  287. template <layout_type L>
  288. using const_reverse_layout_iterator = typename iterable_base::template const_reverse_layout_iterator<L>;
  289. #endif
  290. template <class S, layout_type L>
  291. using broadcast_iterator = typename iterable_base::template broadcast_iterator<S, L>;
  292. template <class S, layout_type L>
  293. using const_broadcast_iterator = typename iterable_base::template const_broadcast_iterator<S, L>;
  294. template <class S, layout_type L>
  295. using reverse_broadcast_iterator = typename iterable_base::template reverse_broadcast_iterator<S, L>;
  296. template <class S, layout_type L>
  297. using const_reverse_broadcast_iterator = typename iterable_base::template const_reverse_broadcast_iterator<S, L>;
  298. using linear_traits = detail::linear_iterator_traits<D>;
  299. using linear_iterator = typename linear_traits::linear_iterator;
  300. using const_linear_iterator = typename linear_traits::const_linear_iterator;
  301. using reverse_linear_iterator = typename linear_traits::reverse_linear_iterator;
  302. using const_reverse_linear_iterator = typename linear_traits::const_reverse_linear_iterator;
  303. template <layout_type L, class It1, class It2>
  304. using select_iterator_impl = std::conditional_t<L == static_layout, It1, It2>;
  305. template <layout_type L>
  306. using select_iterator = select_iterator_impl<L, linear_iterator, layout_iterator<L>>;
  307. template <layout_type L>
  308. using select_const_iterator = select_iterator_impl<L, const_linear_iterator, const_layout_iterator<L>>;
  309. template <layout_type L>
  310. using select_reverse_iterator = select_iterator_impl<L, reverse_linear_iterator, reverse_layout_iterator<L>>;
  311. template <layout_type L>
  312. using select_const_reverse_iterator = select_iterator_impl<
  313. L,
  314. const_reverse_linear_iterator,
  315. const_reverse_layout_iterator<L>>;
  316. using iterator = select_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  317. using const_iterator = select_const_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  318. using reverse_iterator = select_reverse_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  319. using const_reverse_iterator = select_const_reverse_iterator<XTENSOR_DEFAULT_TRAVERSAL>;
  320. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  321. select_iterator<L> begin() noexcept;
  322. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  323. select_iterator<L> end() noexcept;
  324. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  325. select_const_iterator<L> begin() const noexcept;
  326. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  327. select_const_iterator<L> end() const noexcept;
  328. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  329. select_const_iterator<L> cbegin() const noexcept;
  330. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  331. select_const_iterator<L> cend() const noexcept;
  332. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  333. select_reverse_iterator<L> rbegin() noexcept;
  334. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  335. select_reverse_iterator<L> rend() noexcept;
  336. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  337. select_const_reverse_iterator<L> rbegin() const noexcept;
  338. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  339. select_const_reverse_iterator<L> rend() const noexcept;
  340. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  341. select_const_reverse_iterator<L> crbegin() const noexcept;
  342. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL>
  343. select_const_reverse_iterator<L> crend() const noexcept;
  344. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  345. broadcast_iterator<S, L> begin(const S& shape) noexcept;
  346. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  347. broadcast_iterator<S, L> end(const S& shape) noexcept;
  348. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  349. const_broadcast_iterator<S, L> begin(const S& shape) const noexcept;
  350. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  351. const_broadcast_iterator<S, L> end(const S& shape) const noexcept;
  352. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  353. const_broadcast_iterator<S, L> cbegin(const S& shape) const noexcept;
  354. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  355. const_broadcast_iterator<S, L> cend(const S& shape) const noexcept;
  356. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  357. reverse_broadcast_iterator<S, L> rbegin(const S& shape) noexcept;
  358. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  359. reverse_broadcast_iterator<S, L> rend(const S& shape) noexcept;
  360. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  361. const_reverse_broadcast_iterator<S, L> rbegin(const S& shape) const noexcept;
  362. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  363. const_reverse_broadcast_iterator<S, L> rend(const S& shape) const noexcept;
  364. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  365. const_reverse_broadcast_iterator<S, L> crbegin(const S& shape) const noexcept;
  366. template <layout_type L = XTENSOR_DEFAULT_TRAVERSAL, class S>
  367. const_reverse_broadcast_iterator<S, L> crend(const S& shape) const noexcept;
  368. private:
  369. derived_type& derived_cast();
  370. const derived_type& derived_cast() const;
  371. friend class xiterable<D>;
  372. friend class xconst_iterable<D>;
  373. };
  374. /**********************************
  375. * xconst_iterable implementation *
  376. **********************************/
  377. /**
  378. * @name Constant iterators
  379. */
  380. //@{
  381. /**
  382. * Returns a constant iterator to the first element of the expression.
  383. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  384. */
  385. template <class D>
  386. template <layout_type L>
  387. inline auto xconst_iterable<D>::begin() const noexcept -> const_layout_iterator<L>
  388. {
  389. return this->template cbegin<L>();
  390. }
  391. /**
  392. * Returns a constant iterator to the element following the last element
  393. * of the expression.
  394. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  395. */
  396. template <class D>
  397. template <layout_type L>
  398. inline auto xconst_iterable<D>::end() const noexcept -> const_layout_iterator<L>
  399. {
  400. return this->template cend<L>();
  401. }
  402. /**
  403. * Returns a constant iterator to the first element of the expression.
  404. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  405. */
  406. template <class D>
  407. template <layout_type L>
  408. inline auto xconst_iterable<D>::cbegin() const noexcept -> const_layout_iterator<L>
  409. {
  410. return this->template get_cbegin<L>(false);
  411. }
  412. /**
  413. * Returns a constant iterator to the element following the last element
  414. * of the expression.
  415. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  416. */
  417. template <class D>
  418. template <layout_type L>
  419. inline auto xconst_iterable<D>::cend() const noexcept -> const_layout_iterator<L>
  420. {
  421. return this->template get_cend<L>(true);
  422. }
  423. //@}
  424. /**
  425. * @name Constant reverse iterators
  426. */
  427. //@{
  428. /**
  429. * Returns a constant iterator to the first element of the reversed expression.
  430. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  431. */
  432. template <class D>
  433. template <layout_type L>
  434. inline auto xconst_iterable<D>::rbegin() const noexcept -> const_reverse_layout_iterator<L>
  435. {
  436. return this->template crbegin<L>();
  437. }
  438. /**
  439. * Returns a constant iterator to the element following the last element
  440. * of the reversed expression.
  441. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  442. */
  443. template <class D>
  444. template <layout_type L>
  445. inline auto xconst_iterable<D>::rend() const noexcept -> const_reverse_layout_iterator<L>
  446. {
  447. return this->template crend<L>();
  448. }
  449. /**
  450. * Returns a constant iterator to the first element of the reversed expression.
  451. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  452. */
  453. template <class D>
  454. template <layout_type L>
  455. inline auto xconst_iterable<D>::crbegin() const noexcept -> const_reverse_layout_iterator<L>
  456. {
  457. return const_reverse_layout_iterator<L>(get_cend<L>(true));
  458. }
  459. /**
  460. * Returns a constant iterator to the element following the last element
  461. * of the reversed expression.
  462. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  463. */
  464. template <class D>
  465. template <layout_type L>
  466. inline auto xconst_iterable<D>::crend() const noexcept -> const_reverse_layout_iterator<L>
  467. {
  468. return const_reverse_layout_iterator<L>(get_cbegin<L>(false));
  469. }
  470. //@}
  471. /**
  472. * @name Constant broadcast iterators
  473. */
  474. //@{
  475. /**
  476. * Returns a constant iterator to the first element of the expression. The
  477. * iteration is broadcasted to the specified shape.
  478. * @param shape the shape used for broadcasting
  479. * @tparam S type of the \c shape parameter.
  480. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  481. */
  482. template <class D>
  483. template <layout_type L, class S>
  484. inline auto xconst_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  485. {
  486. return cbegin<L>(shape);
  487. }
  488. /**
  489. * Returns a constant iterator to the element following the last element of the
  490. * expression. The iteration is broadcasted to the specified shape.
  491. * @param shape the shape used for broadcasting
  492. * @tparam S type of the \c shape parameter.
  493. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  494. */
  495. template <class D>
  496. template <layout_type L, class S>
  497. inline auto xconst_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  498. {
  499. return cend<L>(shape);
  500. }
  501. /**
  502. * Returns a constant iterator to the first element of the expression. The
  503. * iteration is broadcasted to the specified shape.
  504. * @param shape the shape used for broadcasting
  505. * @tparam S type of the \c shape parameter.
  506. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  507. */
  508. template <class D>
  509. template <layout_type L, class S>
  510. inline auto xconst_iterable<D>::cbegin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  511. {
  512. return get_cbegin<L, S>(shape, false);
  513. }
  514. /**
  515. * Returns a constant iterator to the element following the last element of the
  516. * expression. The iteration is broadcasted to the specified shape.
  517. * @param shape the shape used for broadcasting
  518. * @tparam S type of the \c shape parameter.
  519. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  520. */
  521. template <class D>
  522. template <layout_type L, class S>
  523. inline auto xconst_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  524. {
  525. return get_cend<L, S>(shape, true);
  526. }
  527. //@}
  528. /**
  529. * @name Constant reverse broadcast iterators
  530. */
  531. //@{
  532. /**
  533. * Returns a constant iterator to the first element of the reversed expression.
  534. * The iteration is broadcasted to the specified shape.
  535. * @param shape the shape used for broadcasting
  536. * @tparam S type of the \c shape parameter.
  537. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  538. */
  539. template <class D>
  540. template <layout_type L, class S>
  541. inline auto xconst_iterable<D>::rbegin(const S& shape) const noexcept
  542. -> const_reverse_broadcast_iterator<S, L>
  543. {
  544. return crbegin<L, S>(shape);
  545. }
  546. /**
  547. * Returns a constant iterator to the element following the last element of the
  548. * reversed expression. The iteration is broadcasted to the specified shape.
  549. * @param shape the shape used for broadcasting
  550. * @tparam S type of the \c shape parameter.
  551. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  552. */
  553. template <class D>
  554. template <layout_type L, class S>
  555. inline auto xconst_iterable<D>::rend(const S& shape) const noexcept
  556. -> const_reverse_broadcast_iterator<S, L>
  557. {
  558. return crend<L, S>(shape);
  559. }
  560. /**
  561. * Returns a constant iterator to the first element of the reversed expression.
  562. * The iteration is broadcasted to the specified shape.
  563. * @param shape the shape used for broadcasting
  564. * @tparam S type of the \c shape parameter.
  565. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  566. */
  567. template <class D>
  568. template <layout_type L, class S>
  569. inline auto xconst_iterable<D>::crbegin(const S& shape) const noexcept
  570. -> const_reverse_broadcast_iterator<S, L>
  571. {
  572. return const_reverse_broadcast_iterator<S, L>(get_cend<L, S>(shape, true));
  573. }
  574. /**
  575. * Returns a constant iterator to the element following the last element of the
  576. * reversed expression. The iteration is broadcasted to the specified shape.
  577. * @param shape the shape used for broadcasting
  578. * @tparam S type of the \c shape parameter.
  579. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  580. */
  581. template <class D>
  582. template <layout_type L, class S>
  583. inline auto xconst_iterable<D>::crend(const S& shape) const noexcept
  584. -> const_reverse_broadcast_iterator<S, L>
  585. {
  586. return const_reverse_broadcast_iterator<S, L>(get_cbegin<L, S>(shape, false));
  587. }
  588. //@}
  589. template <class D>
  590. template <layout_type L>
  591. inline auto xconst_iterable<D>::get_cbegin(bool end_index) const noexcept -> const_layout_iterator<L>
  592. {
  593. return const_layout_iterator<L>(get_stepper_begin(get_shape()), &get_shape(), end_index);
  594. }
  595. template <class D>
  596. template <layout_type L>
  597. inline auto xconst_iterable<D>::get_cend(bool end_index) const noexcept -> const_layout_iterator<L>
  598. {
  599. return const_layout_iterator<L>(get_stepper_end(get_shape(), L), &get_shape(), end_index);
  600. }
  601. template <class D>
  602. template <layout_type L, class S>
  603. inline auto xconst_iterable<D>::get_cbegin(const S& shape, bool end_index) const noexcept
  604. -> const_broadcast_iterator<S, L>
  605. {
  606. return const_broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
  607. }
  608. template <class D>
  609. template <layout_type L, class S>
  610. inline auto xconst_iterable<D>::get_cend(const S& shape, bool end_index) const noexcept
  611. -> const_broadcast_iterator<S, L>
  612. {
  613. return const_broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
  614. }
  615. template <class D>
  616. template <class S>
  617. inline auto xconst_iterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
  618. {
  619. return derived_cast().stepper_begin(shape);
  620. }
  621. template <class D>
  622. template <class S>
  623. inline auto xconst_iterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept
  624. -> const_stepper
  625. {
  626. return derived_cast().stepper_end(shape, l);
  627. }
  628. template <class D>
  629. inline auto xconst_iterable<D>::get_shape() const -> const inner_shape_type&
  630. {
  631. return derived_cast().shape();
  632. }
  633. template <class D>
  634. inline auto xconst_iterable<D>::derived_cast() const -> const derived_type&
  635. {
  636. return *static_cast<const derived_type*>(this);
  637. }
  638. /****************************
  639. * xiterable implementation *
  640. ****************************/
  641. /**
  642. * @name Iterators
  643. */
  644. //@{
  645. /**
  646. * Returns an iterator to the first element of the expression.
  647. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  648. */
  649. template <class D>
  650. template <layout_type L>
  651. inline auto xiterable<D>::begin() noexcept -> layout_iterator<L>
  652. {
  653. return get_begin<L>(false);
  654. }
  655. /**
  656. * Returns an iterator to the element following the last element
  657. * of the expression.
  658. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  659. */
  660. template <class D>
  661. template <layout_type L>
  662. inline auto xiterable<D>::end() noexcept -> layout_iterator<L>
  663. {
  664. return get_end<L>(true);
  665. }
  666. //@}
  667. /**
  668. * @name Reverse iterators
  669. */
  670. //@{
  671. /**
  672. * Returns an iterator to the first element of the reversed expression.
  673. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  674. */
  675. template <class D>
  676. template <layout_type L>
  677. inline auto xiterable<D>::rbegin() noexcept -> reverse_layout_iterator<L>
  678. {
  679. return reverse_layout_iterator<L>(get_end<L>(true));
  680. }
  681. /**
  682. * Returns an iterator to the element following the last element
  683. * of the reversed expression.
  684. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  685. */
  686. template <class D>
  687. template <layout_type L>
  688. inline auto xiterable<D>::rend() noexcept -> reverse_layout_iterator<L>
  689. {
  690. return reverse_layout_iterator<L>(get_begin<L>(false));
  691. }
  692. //@}
  693. /**
  694. * @name Broadcast iterators
  695. */
  696. //@{
  697. /**
  698. * Returns an iterator to the first element of the expression. The
  699. * iteration is broadcasted to the specified shape.
  700. * @param shape the shape used for broadcasting
  701. * @tparam S type of the \c shape parameter.
  702. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  703. */
  704. template <class D>
  705. template <layout_type L, class S>
  706. inline auto xiterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
  707. {
  708. return get_begin<L, S>(shape, false);
  709. }
  710. /**
  711. * Returns an iterator to the element following the last element of the
  712. * expression. The iteration is broadcasted to the specified shape.
  713. * @param shape the shape used for broadcasting
  714. * @tparam S type of the \c shape parameter.
  715. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  716. */
  717. template <class D>
  718. template <layout_type L, class S>
  719. inline auto xiterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
  720. {
  721. return get_end<L, S>(shape, true);
  722. }
  723. //@}
  724. /**
  725. * @name Reverse broadcast iterators
  726. */
  727. //@{
  728. /**
  729. * Returns an iterator to the first element of the reversed expression. The
  730. * iteration is broadcasted to the specified shape.
  731. * @param shape the shape used for broadcasting
  732. * @tparam S type of the \c shape parameter.
  733. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  734. */
  735. template <class D>
  736. template <layout_type L, class S>
  737. inline auto xiterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  738. {
  739. return reverse_broadcast_iterator<S, L>(get_end<L, S>(shape, true));
  740. }
  741. /**
  742. * Returns an iterator to the element following the last element of the
  743. * reversed expression. The iteration is broadcasted to the specified shape.
  744. * @param shape the shape used for broadcasting
  745. * @tparam S type of the \c shape parameter.
  746. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  747. */
  748. template <class D>
  749. template <layout_type L, class S>
  750. inline auto xiterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  751. {
  752. return reverse_broadcast_iterator<S, L>(get_begin<L, S>(shape, false));
  753. }
  754. //@}
  755. template <class D>
  756. template <layout_type L>
  757. inline auto xiterable<D>::get_begin(bool end_index) noexcept -> layout_iterator<L>
  758. {
  759. return layout_iterator<L>(get_stepper_begin(this->get_shape()), &(this->get_shape()), end_index);
  760. }
  761. template <class D>
  762. template <layout_type L>
  763. inline auto xiterable<D>::get_end(bool end_index) noexcept -> layout_iterator<L>
  764. {
  765. return layout_iterator<L>(get_stepper_end(this->get_shape(), L), &(this->get_shape()), end_index);
  766. }
  767. template <class D>
  768. template <layout_type L, class S>
  769. inline auto xiterable<D>::get_begin(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
  770. {
  771. return broadcast_iterator<S, L>(get_stepper_begin(shape), shape, end_index);
  772. }
  773. template <class D>
  774. template <layout_type L, class S>
  775. inline auto xiterable<D>::get_end(const S& shape, bool end_index) noexcept -> broadcast_iterator<S, L>
  776. {
  777. return broadcast_iterator<S, L>(get_stepper_end(shape, L), shape, end_index);
  778. }
  779. template <class D>
  780. template <class S>
  781. inline auto xiterable<D>::get_stepper_begin(const S& shape) noexcept -> stepper
  782. {
  783. return derived_cast().stepper_begin(shape);
  784. }
  785. template <class D>
  786. template <class S>
  787. inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) noexcept -> stepper
  788. {
  789. return derived_cast().stepper_end(shape, l);
  790. }
  791. template <class D>
  792. template <class S>
  793. inline auto xiterable<D>::get_stepper_begin(const S& shape) const noexcept -> const_stepper
  794. {
  795. return derived_cast().stepper_begin(shape);
  796. }
  797. template <class D>
  798. template <class S>
  799. inline auto xiterable<D>::get_stepper_end(const S& shape, layout_type l) const noexcept -> const_stepper
  800. {
  801. return derived_cast().stepper_end(shape, l);
  802. }
  803. template <class D>
  804. inline auto xiterable<D>::derived_cast() -> derived_type&
  805. {
  806. return *static_cast<derived_type*>(this);
  807. }
  808. /***************************************
  809. * xcontiguous_iterable implementation *
  810. ***************************************/
  811. /**
  812. * @name Iterators
  813. */
  814. //@{
  815. /**
  816. * Returns an iterator to the first element of the expression.
  817. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  818. */
  819. template <class D>
  820. template <layout_type L>
  821. inline auto xcontiguous_iterable<D>::begin() noexcept -> select_iterator<L>
  822. {
  823. return xtl::mpl::static_if<L == static_layout>(
  824. [&](auto self)
  825. {
  826. return self(*this).derived_cast().linear_begin();
  827. },
  828. /*else*/
  829. [&](auto self)
  830. {
  831. return self(*this).iterable_base::template begin<L>();
  832. }
  833. );
  834. }
  835. /**
  836. * Returns an iterator to the element following the last element
  837. * of the expression.
  838. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  839. */
  840. template <class D>
  841. template <layout_type L>
  842. inline auto xcontiguous_iterable<D>::end() noexcept -> select_iterator<L>
  843. {
  844. return xtl::mpl::static_if<L == static_layout>(
  845. [&](auto self)
  846. {
  847. return self(*this).derived_cast().linear_end();
  848. },
  849. /*else*/
  850. [&](auto self)
  851. {
  852. return self(*this).iterable_base::template end<L>();
  853. }
  854. );
  855. }
  856. /**
  857. * Returns a constant iterator to the first element of the expression.
  858. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  859. */
  860. template <class D>
  861. template <layout_type L>
  862. inline auto xcontiguous_iterable<D>::begin() const noexcept -> select_const_iterator<L>
  863. {
  864. return this->template cbegin<L>();
  865. }
  866. /**
  867. * Returns a constant iterator to the element following the last element
  868. * of the expression.
  869. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  870. */
  871. template <class D>
  872. template <layout_type L>
  873. inline auto xcontiguous_iterable<D>::end() const noexcept -> select_const_iterator<L>
  874. {
  875. return this->template cend<L>();
  876. }
  877. /**
  878. * Returns a constant iterator to the first element of the expression.
  879. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  880. */
  881. template <class D>
  882. template <layout_type L>
  883. inline auto xcontiguous_iterable<D>::cbegin() const noexcept -> select_const_iterator<L>
  884. {
  885. return xtl::mpl::static_if<L == static_layout>(
  886. [&](auto self)
  887. {
  888. return self(*this).derived_cast().linear_cbegin();
  889. },
  890. /*else*/
  891. [&](auto self)
  892. {
  893. return self(*this).iterable_base::template cbegin<L>();
  894. }
  895. );
  896. }
  897. /**
  898. * Returns a constant iterator to the element following the last element
  899. * of the expression.
  900. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  901. */
  902. template <class D>
  903. template <layout_type L>
  904. inline auto xcontiguous_iterable<D>::cend() const noexcept -> select_const_iterator<L>
  905. {
  906. return xtl::mpl::static_if<L == static_layout>(
  907. [&](auto self)
  908. {
  909. return self(*this).derived_cast().linear_cend();
  910. },
  911. /*else*/
  912. [&](auto self)
  913. {
  914. return self(*this).iterable_base::template cend<L>();
  915. }
  916. );
  917. }
  918. //@}
  919. /**
  920. * @name Reverse iterators
  921. */
  922. //@{
  923. /**
  924. * Returns an iterator to the first element of the reversed expression.
  925. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  926. */
  927. template <class D>
  928. template <layout_type L>
  929. inline auto xcontiguous_iterable<D>::rbegin() noexcept -> select_reverse_iterator<L>
  930. {
  931. return xtl::mpl::static_if<L == static_layout>(
  932. [&](auto self)
  933. {
  934. return self(*this).derived_cast().linear_rbegin();
  935. },
  936. /*else*/
  937. [&](auto self)
  938. {
  939. return self(*this).iterable_base::template rbegin<L>();
  940. }
  941. );
  942. }
  943. /**
  944. * Returns an iterator to the element following the last element
  945. * of the reversed expression.
  946. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  947. */
  948. template <class D>
  949. template <layout_type L>
  950. inline auto xcontiguous_iterable<D>::rend() noexcept -> select_reverse_iterator<L>
  951. {
  952. return xtl::mpl::static_if<L == static_layout>(
  953. [&](auto self)
  954. {
  955. return self(*this).derived_cast().linear_rend();
  956. },
  957. /*else*/
  958. [&](auto self)
  959. {
  960. return self(*this).iterable_base::template rend<L>();
  961. }
  962. );
  963. }
  964. /**
  965. * Returns a constant iterator to the first element of the reversed expression.
  966. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  967. */
  968. template <class D>
  969. template <layout_type L>
  970. inline auto xcontiguous_iterable<D>::rbegin() const noexcept -> select_const_reverse_iterator<L>
  971. {
  972. return this->template crbegin<L>();
  973. }
  974. /**
  975. * Returns a constant iterator to the element following the last element
  976. * of the reversed expression.
  977. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  978. */
  979. template <class D>
  980. template <layout_type L>
  981. inline auto xcontiguous_iterable<D>::rend() const noexcept -> select_const_reverse_iterator<L>
  982. {
  983. return this->template crend<L>();
  984. }
  985. /**
  986. * Returns a constant iterator to the first element of the reversed expression.
  987. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  988. */
  989. template <class D>
  990. template <layout_type L>
  991. inline auto xcontiguous_iterable<D>::crbegin() const noexcept -> select_const_reverse_iterator<L>
  992. {
  993. return xtl::mpl::static_if<L == static_layout>(
  994. [&](auto self)
  995. {
  996. return self(*this).derived_cast().linear_crbegin();
  997. },
  998. /*else*/
  999. [&](auto self)
  1000. {
  1001. return self(*this).iterable_base::template crbegin<L>();
  1002. }
  1003. );
  1004. }
  1005. /**
  1006. * Returns a constant iterator to the element following the last element
  1007. * of the reversed expression.
  1008. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1009. */
  1010. template <class D>
  1011. template <layout_type L>
  1012. inline auto xcontiguous_iterable<D>::crend() const noexcept -> select_const_reverse_iterator<L>
  1013. {
  1014. return xtl::mpl::static_if<L == static_layout>(
  1015. [&](auto self)
  1016. {
  1017. return self(*this).derived_cast().linear_crend();
  1018. },
  1019. /*else*/
  1020. [&](auto self)
  1021. {
  1022. return self(*this).iterable_base::template crend<L>();
  1023. }
  1024. );
  1025. }
  1026. //@}
  1027. /**
  1028. * @name Broadcast iterators
  1029. */
  1030. /**
  1031. * Returns an iterator to the first element of the expression. The
  1032. * iteration is broadcasted to the specified shape.
  1033. * @param shape the shape used for broadcasting
  1034. * @tparam S type of the \c shape parameter.
  1035. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1036. */
  1037. //@{
  1038. template <class D>
  1039. template <layout_type L, class S>
  1040. inline auto xcontiguous_iterable<D>::begin(const S& shape) noexcept -> broadcast_iterator<S, L>
  1041. {
  1042. return iterable_base::template begin<L, S>(shape);
  1043. }
  1044. /**
  1045. * Returns an iterator to the element following the last element of the
  1046. * expression. The iteration is broadcasted to the specified shape.
  1047. * @param shape the shape used for broadcasting
  1048. * @tparam S type of the \c shape parameter.
  1049. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1050. */
  1051. template <class D>
  1052. template <layout_type L, class S>
  1053. inline auto xcontiguous_iterable<D>::end(const S& shape) noexcept -> broadcast_iterator<S, L>
  1054. {
  1055. return iterable_base::template end<L, S>(shape);
  1056. }
  1057. /**
  1058. * Returns a constant iterator to the first element of the expression. The
  1059. * iteration is broadcasted to the specified shape.
  1060. * @param shape the shape used for broadcasting
  1061. * @tparam S type of the \c shape parameter.
  1062. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1063. */
  1064. template <class D>
  1065. template <layout_type L, class S>
  1066. inline auto xcontiguous_iterable<D>::begin(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  1067. {
  1068. return iterable_base::template begin<L, S>(shape);
  1069. }
  1070. /**
  1071. * Returns a constant iterator to the element following the last element of the
  1072. * expression. The iteration is broadcasted to the specified shape.
  1073. * @param shape the shape used for broadcasting
  1074. * @tparam S type of the \c shape parameter.
  1075. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1076. */
  1077. template <class D>
  1078. template <layout_type L, class S>
  1079. inline auto xcontiguous_iterable<D>::end(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  1080. {
  1081. return iterable_base::template end<L, S>(shape);
  1082. }
  1083. /**
  1084. * Returns a constant iterator to the first element of the expression. The
  1085. * iteration is broadcasted to the specified shape.
  1086. * @param shape the shape used for broadcasting
  1087. * @tparam S type of the \c shape parameter.
  1088. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1089. */
  1090. template <class D>
  1091. template <layout_type L, class S>
  1092. inline auto xcontiguous_iterable<D>::cbegin(const S& shape) const noexcept
  1093. -> const_broadcast_iterator<S, L>
  1094. {
  1095. return iterable_base::template cbegin<L, S>(shape);
  1096. }
  1097. /**
  1098. * Returns a constant iterator to the element following the last element of the
  1099. * expression. The iteration is broadcasted to the specified shape.
  1100. * @param shape the shape used for broadcasting
  1101. * @tparam S type of the \c shape parameter.
  1102. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1103. */
  1104. template <class D>
  1105. template <layout_type L, class S>
  1106. inline auto xcontiguous_iterable<D>::cend(const S& shape) const noexcept -> const_broadcast_iterator<S, L>
  1107. {
  1108. return iterable_base::template cend<L, S>(shape);
  1109. }
  1110. //@}
  1111. /**
  1112. * @name Reverse broadcast iterators
  1113. */
  1114. //@{
  1115. /**
  1116. * Returns an iterator to the first element of the reversed expression. The
  1117. * iteration is broadcasted to the specified shape.
  1118. * @param shape the shape used for broadcasting
  1119. * @tparam S type of the \c shape parameter.
  1120. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1121. */
  1122. template <class D>
  1123. template <layout_type L, class S>
  1124. inline auto xcontiguous_iterable<D>::rbegin(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  1125. {
  1126. return iterable_base::template rbegin<L, S>(shape);
  1127. }
  1128. /**
  1129. * Returns an iterator to the element following the last element of the
  1130. * reversed expression. The iteration is broadcasted to the specified shape.
  1131. * @param shape the shape used for broadcasting
  1132. * @tparam S type of the \c shape parameter.
  1133. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1134. */
  1135. template <class D>
  1136. template <layout_type L, class S>
  1137. inline auto xcontiguous_iterable<D>::rend(const S& shape) noexcept -> reverse_broadcast_iterator<S, L>
  1138. {
  1139. return iterable_base::template rend<L, S>(shape);
  1140. }
  1141. /**
  1142. * Returns a constant iterator to the first element of the reversed expression.
  1143. * The iteration is broadcasted to the specified shape.
  1144. * @param shape the shape used for broadcasting
  1145. * @tparam S type of the \c shape parameter.
  1146. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1147. */
  1148. template <class D>
  1149. template <layout_type L, class S>
  1150. inline auto xcontiguous_iterable<D>::rbegin(const S& shape) const noexcept
  1151. -> const_reverse_broadcast_iterator<S, L>
  1152. {
  1153. return iterable_base::template rbegin<L, S>(shape);
  1154. }
  1155. /**
  1156. * Returns a constant iterator to the element following the last element of the
  1157. * reversed expression. The iteration is broadcasted to the specified shape.
  1158. * @param shape the shape used for broadcasting
  1159. * @tparam S type of the \c shape parameter.
  1160. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1161. */
  1162. template <class D>
  1163. template <layout_type L, class S>
  1164. inline auto xcontiguous_iterable<D>::rend(const S& shape) const noexcept
  1165. -> const_reverse_broadcast_iterator<S, L>
  1166. {
  1167. return iterable_base::template rend<L, S>(shape);
  1168. }
  1169. /**
  1170. * Returns a constant iterator to the first element of the reversed expression.
  1171. * The iteration is broadcasted to the specified shape.
  1172. * @param shape the shape used for broadcasting
  1173. * @tparam S type of the \c shape parameter.
  1174. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1175. */
  1176. template <class D>
  1177. template <layout_type L, class S>
  1178. inline auto xcontiguous_iterable<D>::crbegin(const S& shape) const noexcept
  1179. -> const_reverse_broadcast_iterator<S, L>
  1180. {
  1181. return iterable_base::template crbegin<L, S>(shape);
  1182. }
  1183. /**
  1184. * Returns a constant iterator to the element following the last element of the
  1185. * reversed expression. The iteration is broadcasted to the specified shape.
  1186. * @param shape the shape used for broadcasting
  1187. * @tparam S type of the \c shape parameter.
  1188. * @tparam L order used for the traversal. Default value is \c XTENSOR_DEFAULT_TRAVERSAL.
  1189. */
  1190. template <class D>
  1191. template <layout_type L, class S>
  1192. inline auto xcontiguous_iterable<D>::crend(const S& shape) const noexcept
  1193. -> const_reverse_broadcast_iterator<S, L>
  1194. {
  1195. return iterable_base::template crend<L, S>(shape);
  1196. }
  1197. //@}
  1198. template <class D>
  1199. inline auto xcontiguous_iterable<D>::derived_cast() -> derived_type&
  1200. {
  1201. return *static_cast<derived_type*>(this);
  1202. }
  1203. template <class D>
  1204. inline auto xcontiguous_iterable<D>::derived_cast() const -> const derived_type&
  1205. {
  1206. return *static_cast<const derived_type*>(this);
  1207. }
  1208. }
  1209. #endif