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