1 /*========================================================================= 2 3 Program: Visualization Toolkit 4 Module: vtkDataArrayTupleRange_Generic.h 5 6 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 7 All rights reserved. 8 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 9 10 This software is distributed WITHOUT ANY WARRANTY; without even 11 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 12 PURPOSE. See the above copyright notice for more information. 13 14 =========================================================================*/ 15 /** 16 * Generic implementation of value ranges and iterators, suitable for 17 * vtkDataArray and all subclasses. 18 */ 19 20 #ifndef vtkDataArrayTupleRange_Generic_h 21 #define vtkDataArrayTupleRange_Generic_h 22 23 #include "vtkAssume.h" 24 #include "vtkDataArrayAccessor.h" 25 #include "vtkDataArrayMeta.h" 26 27 #include <algorithm> 28 #include <cassert> 29 #include <iterator> 30 #include <type_traits> 31 32 #ifndef __VTK_WRAP__ 33 34 VTK_ITER_OPTIMIZE_START 35 36 namespace vtk 37 { 38 39 namespace detail 40 { 41 42 // Forward decs for friends/args 43 template <typename ArrayType, ComponentIdType> 44 struct ConstComponentReference; 45 template <typename ArrayType, ComponentIdType> 46 struct ComponentReference; 47 template <typename ArrayType, ComponentIdType> 48 struct ConstComponentIterator; 49 template <typename ArrayType, ComponentIdType> 50 struct ComponentIterator; 51 template <typename ArrayType, ComponentIdType> 52 struct ConstTupleReference; 53 template <typename ArrayType, ComponentIdType> 54 struct TupleReference; 55 template <typename ArrayType, ComponentIdType> 56 struct ConstTupleIterator; 57 template <typename ArrayType, ComponentIdType> 58 struct TupleIterator; 59 template <typename ArrayType, ComponentIdType> 60 struct TupleRange; 61 62 //------------------------------------------------------------------------------ 63 // Const component reference 64 template <typename ArrayType, ComponentIdType TupleSize> 65 struct ConstComponentReference 66 { 67 private: 68 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 69 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 70 71 using NumCompsType = GenericTupleSize<TupleSize>; 72 using APIType = GetAPIType<ArrayType>; 73 74 public: 75 using value_type = APIType; 76 77 VTK_ITER_INLINE ConstComponentReferenceConstComponentReference78 ConstComponentReference() noexcept 79 : Array{ nullptr } 80 , NumComps{} 81 , TupleId{ 0 } 82 , ComponentId{ 0 } 83 { 84 } 85 86 VTK_ITER_INLINE ConstComponentReferenceConstComponentReference87 ConstComponentReference( 88 ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept 89 : Array{ array } 90 , NumComps{ numComps } 91 , TupleId{ tuple } 92 , ComponentId{ comp } 93 { 94 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 95 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 96 VTK_ITER_ASSERT( 97 tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator."); 98 VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(), 99 "Invalid component accessed by iterator."); 100 } 101 102 VTK_ITER_INLINE ConstComponentReferenceConstComponentReference103 ConstComponentReference(const ComponentReference<ArrayType, TupleSize>& o) 104 : Array{ o.Array } 105 , NumComps{ o.NumComps } 106 , TupleId{ o.TupleId } 107 , ComponentId{ o.ComponentId } 108 { 109 } 110 111 VTK_ITER_INLINE 112 ConstComponentReference(const ConstComponentReference& o) noexcept = default; 113 114 VTK_ITER_INLINE 115 ConstComponentReference(ConstComponentReference&& o) noexcept = default; 116 117 VTK_ITER_INLINE 118 ConstComponentReference& operator=(const ConstComponentReference& o) noexcept 119 { 120 VTK_ITER_ASSERT(!this->Array, "Const reference already initialized."); 121 // Initialize the reference. 122 this->Array = o.Array; 123 this->NumComps = o.NumComps; 124 this->TupleId = o.TupleId; 125 this->ComponentId = o.ComponentId; 126 } 127 128 VTK_ITER_INLINE 129 ConstComponentReference& operator=(ConstComponentReference&& o) noexcept 130 { 131 VTK_ITER_ASSERT(!this->Array, "Const reference already initialized."); 132 // Initialize the reference. 133 this->Array = std::move(o.Array); 134 this->NumComps = std::move(o.NumComps); 135 this->TupleId = std::move(o.TupleId); 136 this->ComponentId = std::move(o.ComponentId); 137 } 138 139 VTK_ITER_INLINE APITypeConstComponentReference140 operator APIType() const noexcept 141 { 142 VTK_ITER_ASSUME(this->NumComps.value > 0); 143 VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value); 144 vtkDataArrayAccessor<ArrayType> acc{ this->Array }; 145 return acc.Get(this->TupleId, this->ComponentId); 146 } 147 148 protected: 149 mutable ArrayType* Array; 150 NumCompsType NumComps; 151 TupleIdType TupleId; 152 ComponentIdType ComponentId; 153 }; 154 155 //------------------------------------------------------------------------------ 156 // Component reference 157 template <typename ArrayType, ComponentIdType TupleSize> 158 struct ComponentReference 159 { 160 private: 161 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 162 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 163 164 using NumCompsType = GenericTupleSize<TupleSize>; 165 using APIType = GetAPIType<ArrayType>; 166 167 public: 168 using value_type = APIType; 169 170 VTK_ITER_INLINE ComponentReferenceComponentReference171 ComponentReference() noexcept 172 : Array{ nullptr } 173 , NumComps{} 174 , TupleId{ 0 } 175 , ComponentId{ 0 } 176 { 177 } 178 179 VTK_ITER_INLINE ComponentReferenceComponentReference180 ComponentReference( 181 ArrayType* array, NumCompsType numComps, TupleIdType tuple, ComponentIdType comp) noexcept 182 : Array{ array } 183 , NumComps{ numComps } 184 , TupleId{ tuple } 185 , ComponentId{ comp } 186 { 187 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 188 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 189 VTK_ITER_ASSERT( 190 tuple >= 0 && tuple <= array->GetNumberOfTuples(), "Invalid tuple accessed by iterator."); 191 VTK_ITER_ASSERT(comp >= 0 && comp <= array->GetNumberOfComponents(), 192 "Invalid component accessed by iterator."); 193 } 194 195 VTK_ITER_INLINE 196 ComponentReference(const ComponentReference& o) noexcept = default; 197 VTK_ITER_INLINE 198 ComponentReference(ComponentReference&& o) noexcept = default; 199 200 VTK_ITER_INLINE 201 ComponentReference operator=(const ComponentReference& o) noexcept 202 { 203 if (this->Array) 204 { // Already initialized. Assign the value, not the reference 205 return *this = static_cast<APIType>(o); 206 } 207 else 208 { // Initialize the reference. 209 this->Array = o.Array; 210 this->NumComps = o.NumComps; 211 this->TupleId = o.TupleId; 212 this->ComponentId = o.ComponentId; 213 214 return *this; 215 } 216 } 217 218 VTK_ITER_INLINE 219 ComponentReference operator=(ComponentReference&& o) noexcept 220 { 221 if (this->Array) 222 { // Already initialized. Assign the value, not the reference 223 return *this = std::move(static_cast<APIType>(o)); 224 } 225 else 226 { // Initialize the reference. 227 this->Array = std::move(o.Array); 228 this->NumComps = std::move(o.NumComps); 229 this->TupleId = std::move(o.TupleId); 230 this->ComponentId = std::move(o.ComponentId); 231 232 return *this; 233 } 234 } 235 236 template <typename OArray, ComponentIdType OSize> 237 VTK_ITER_INLINE ComponentReference operator=(const ComponentReference<OArray, OSize>& o) noexcept 238 { // Always copy the value for different reference types: 239 const APIType tmp = o; 240 return *this = std::move(tmp); 241 } 242 243 VTK_ITER_INLINE APITypeComponentReference244 operator APIType() const noexcept 245 { 246 VTK_ITER_ASSUME(this->NumComps.value > 0); 247 VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value); 248 vtkDataArrayAccessor<ArrayType> acc{ this->Array }; 249 return acc.Get(this->TupleId, this->ComponentId); 250 } 251 252 VTK_ITER_INLINE 253 ComponentReference operator=(APIType val) noexcept 254 { 255 VTK_ITER_ASSUME(this->NumComps.value > 0); 256 VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value); 257 vtkDataArrayAccessor<ArrayType> acc{ this->Array }; 258 acc.Set(this->TupleId, this->ComponentId, val); 259 return *this; 260 } 261 swapComponentReference262 friend VTK_ITER_INLINE void swap(ComponentReference lhs, ComponentReference rhs) noexcept 263 { // Swap values, not references: 264 APIType tmp = std::move(static_cast<APIType>(lhs)); 265 lhs = std::move(static_cast<APIType>(rhs)); 266 rhs = std::move(tmp); 267 } 268 269 template <typename OArray, ComponentIdType OSize> swapComponentReference270 friend VTK_ITER_INLINE void swap( 271 ComponentReference lhs, ComponentReference<OArray, OSize> rhs) noexcept 272 { // Swap values, not references: 273 using OAPIType = GetAPIType<OArray>; 274 static_assert( 275 std::is_same<APIType, OAPIType>::value, "Cannot swap components with different types."); 276 277 APIType tmp = std::move(static_cast<APIType>(lhs)); 278 lhs = std::move(static_cast<APIType>(rhs)); 279 rhs = std::move(tmp); 280 } 281 swapComponentReference282 friend VTK_ITER_INLINE void swap(ComponentReference lhs, APIType& rhs) noexcept 283 { 284 APIType tmp = std::move(static_cast<APIType>(lhs)); 285 lhs = std::move(rhs); 286 rhs = std::move(tmp); 287 } 288 swapComponentReference289 friend VTK_ITER_INLINE void swap(APIType& lhs, ComponentReference rhs) noexcept 290 { 291 APIType tmp = std::move(lhs); 292 lhs = std::move(static_cast<APIType>(rhs)); 293 rhs = std::move(tmp); 294 } 295 296 VTK_ITER_INLINE 297 ComponentReference operator++() noexcept // prefix 298 { 299 const APIType newVal = *this + 1; 300 *this = newVal; 301 return *this; 302 } 303 304 VTK_ITER_INLINE 305 APIType operator++(int) noexcept // postfix 306 { 307 const APIType retVal = *this; 308 *this = *this + 1; 309 return retVal; 310 } 311 312 VTK_ITER_INLINE 313 ComponentReference operator--() noexcept // prefix 314 { 315 const APIType newVal = *this - 1; 316 *this = newVal; 317 return *this; 318 } 319 320 VTK_ITER_INLINE 321 APIType operator--(int) noexcept // postfix 322 { 323 const APIType retVal = *this; 324 *this = *this - 1; 325 return retVal; 326 } 327 328 #define VTK_REF_OP_OVERLOADS(Op, ImplOp) \ 329 friend VTK_ITER_INLINE ComponentReference operator Op( \ 330 ComponentReference lhs, APIType val) noexcept \ 331 { \ 332 const APIType newVal = lhs ImplOp val; \ 333 lhs = newVal; \ 334 return lhs; \ 335 } \ 336 friend VTK_ITER_INLINE ComponentReference operator Op( \ 337 ComponentReference lhs, ComponentReference val) noexcept \ 338 { \ 339 const APIType newVal = lhs ImplOp val; \ 340 lhs = newVal; \ 341 return lhs; \ 342 } \ 343 friend VTK_ITER_INLINE APIType& operator Op(APIType& lhs, ComponentReference val) noexcept \ 344 { \ 345 const APIType newVal = lhs ImplOp val; \ 346 lhs = newVal; \ 347 return lhs; \ 348 } 349 350 VTK_REF_OP_OVERLOADS(+=, +) 351 VTK_REF_OP_OVERLOADS(-=, -) 352 VTK_REF_OP_OVERLOADS(*=, *) 353 VTK_REF_OP_OVERLOADS(/=, /) 354 355 #undef VTK_REF_OP_OVERLOADS 356 357 friend struct ConstComponentReference<ArrayType, TupleSize>; 358 friend struct ComponentIterator<ArrayType, TupleSize>; 359 360 protected: 361 VTK_ITER_INLINE 362 void CopyReference(const ComponentReference& o) noexcept 363 { 364 this->Array = o.Array; 365 this->NumComps = o.NumComps; 366 this->TupleId = o.TupleId; 367 this->ComponentId = o.ComponentId; 368 } 369 370 mutable ArrayType* Array; 371 NumCompsType NumComps; 372 TupleIdType TupleId; 373 ComponentIdType ComponentId; 374 }; 375 376 //------------------------------------------------------------------------------ 377 // Const component iterator 378 template <typename ArrayType, ComponentIdType TupleSize> 379 struct ConstComponentIterator 380 { 381 private: 382 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 383 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 384 385 using NumCompsType = GenericTupleSize<TupleSize>; 386 387 public: 388 using iterator_category = std::random_access_iterator_tag; 389 using value_type = GetAPIType<ArrayType>; 390 using difference_type = ComponentIdType; 391 using pointer = void; 392 using reference = ConstComponentReference<ArrayType, TupleSize>; 393 394 VTK_ITER_INLINE 395 ConstComponentIterator() noexcept 396 : Array{ nullptr } 397 , TupleId{ 0 } 398 , ComponentId{ 0 } 399 { 400 } 401 402 VTK_ITER_INLINE 403 ConstComponentIterator( 404 ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept 405 : Array(array) 406 , NumComps(numComps) 407 , TupleId(tupleId) 408 , ComponentId(comp) 409 { 410 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 411 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 412 VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), 413 "Const component iterator at invalid tuple id."); 414 VTK_ITER_ASSERT(comp >= 0 && comp <= this->NumComps.value, 415 "Const component iterator at invalid component id."); 416 } 417 418 VTK_ITER_INLINE 419 ConstComponentIterator(const ComponentIterator<ArrayType, TupleSize>& o) noexcept 420 : Array{ o.GetArray() } 421 , NumComps{ o.GetNumComps() } 422 , TupleId{ o.GetTupleId() } 423 , ComponentId{ o.GetComponentId() } 424 { 425 } 426 427 VTK_ITER_INLINE 428 ConstComponentIterator(const ConstComponentIterator& o) noexcept = default; 429 VTK_ITER_INLINE 430 ConstComponentIterator& operator=(const ConstComponentIterator& o) noexcept = default; 431 432 VTK_ITER_INLINE 433 ConstComponentIterator& operator++() noexcept // prefix 434 { 435 ++this->ComponentId; 436 VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value, 437 "Const component iterator at invalid component id."); 438 return *this; 439 } 440 441 VTK_ITER_INLINE 442 ConstComponentIterator operator++(int) noexcept // postfix 443 { 444 return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId, 445 this->ComponentId++ }; 446 } 447 448 VTK_ITER_INLINE 449 ConstComponentIterator& operator--() noexcept // prefix 450 { 451 --this->ComponentId; 452 VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value, 453 "Const component iterator at invalid component id."); 454 return *this; 455 } 456 457 VTK_ITER_INLINE 458 ConstComponentIterator operator--(int) noexcept // postfix 459 { 460 return ConstComponentIterator{ this->Array, this->NumComps, this->TupleId, 461 this->ComponentId-- }; 462 } 463 464 VTK_ITER_INLINE 465 reference operator[](difference_type i) const noexcept 466 { 467 return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId + i }; 468 } 469 470 VTK_ITER_INLINE 471 reference operator*() const noexcept 472 { 473 return reference{ this->Array, this->NumComps, this->TupleId, this->ComponentId }; 474 } 475 476 #define VTK_TMP_MAKE_OPERATOR(OP) \ 477 friend VTK_ITER_INLINE bool operator OP( \ 478 const ConstComponentIterator& lhs, const ConstComponentIterator& rhs) noexcept \ 479 { \ 480 VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Mismatched arrays in iterator comparison."); \ 481 VTK_ITER_ASSERT(lhs.TupleId == rhs.TupleId, "Mismatched tuple ids in iterator comparison."); \ 482 VTK_ITER_ASSUME(lhs.NumComps.value > 0); \ 483 VTK_ITER_ASSUME(lhs.NumComps.value == rhs.NumComps.value); \ 484 return lhs.ComponentId OP rhs.ComponentId; \ 485 } 486 487 VTK_TMP_MAKE_OPERATOR(==) 488 VTK_TMP_MAKE_OPERATOR(!=) 489 VTK_TMP_MAKE_OPERATOR(<) 490 VTK_TMP_MAKE_OPERATOR(>) 491 VTK_TMP_MAKE_OPERATOR(<=) 492 VTK_TMP_MAKE_OPERATOR(>=) 493 494 #undef VTK_TMP_MAKE_OPERATOR 495 496 VTK_ITER_INLINE 497 ConstComponentIterator& operator+=(difference_type offset) noexcept 498 { 499 this->ComponentId += offset; 500 VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value, 501 "Const component iterator at invalid component id."); 502 return *this; 503 } 504 505 friend VTK_ITER_INLINE ConstComponentIterator operator+( 506 const ConstComponentIterator& it, difference_type offset) noexcept 507 { 508 return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset }; 509 } 510 511 friend VTK_ITER_INLINE ConstComponentIterator operator+( 512 difference_type offset, const ConstComponentIterator& it) noexcept 513 { 514 return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId + offset }; 515 } 516 517 VTK_ITER_INLINE 518 ConstComponentIterator& operator-=(difference_type offset) noexcept 519 { 520 this->ComponentId -= offset; 521 VTK_ITER_ASSERT(this->ComponentId >= 0 && this->ComponentId <= this->NumComps.value, 522 "Const component iterator at invalid component id."); 523 return *this; 524 } 525 526 friend VTK_ITER_INLINE ConstComponentIterator operator-( 527 const ConstComponentIterator& it, difference_type offset) noexcept 528 { 529 return ConstComponentIterator{ it.Array, it.NumComps, it.TupleId, it.ComponentId - offset }; 530 } 531 532 friend VTK_ITER_INLINE difference_type operator-( 533 const ConstComponentIterator& it1, const ConstComponentIterator& it2) noexcept 534 { 535 VTK_ITER_ASSERT(it1.Array == it2.Array, "Cannot do math with iterators from different arrays."); 536 VTK_ITER_ASSERT(it1.TupleId == it2.TupleId, 537 "Cannot do math with component iterators from different " 538 "tuples."); 539 return it1.ComponentId - it2.ComponentId; 540 } 541 542 friend VTK_ITER_INLINE void swap( 543 ConstComponentIterator& lhs, ConstComponentIterator& rhs) noexcept 544 { 545 // Different arrays may use different iterator implementations. 546 VTK_ITER_ASSERT(lhs.Array == rhs.Array, "Cannot swap iterators from different arrays."); 547 548 using std::swap; 549 swap(lhs.TupleId, rhs.TupleId); 550 swap(lhs.ComponentId, rhs.ComponentId); 551 } 552 553 private: 554 mutable ArrayType* Array; 555 NumCompsType NumComps; 556 TupleIdType TupleId; 557 ComponentIdType ComponentId; 558 }; 559 560 //------------------------------------------------------------------------------ 561 // Component iterator 562 template <typename ArrayType, ComponentIdType TupleSize> 563 struct ComponentIterator 564 { 565 private: 566 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 567 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 568 569 using NumCompsType = GenericTupleSize<TupleSize>; 570 using APIType = GetAPIType<ArrayType>; 571 572 public: 573 using iterator_category = std::random_access_iterator_tag; 574 using value_type = APIType; 575 using difference_type = ComponentIdType; 576 using pointer = ComponentReference<ArrayType, TupleSize>; 577 using reference = ComponentReference<ArrayType, TupleSize>; 578 579 VTK_ITER_INLINE 580 ComponentIterator() noexcept = default; 581 582 VTK_ITER_INLINE 583 ComponentIterator( 584 ArrayType* array, NumCompsType numComps, TupleIdType tupleId, ComponentIdType comp) noexcept 585 : Ref(array, numComps, tupleId, comp) 586 { 587 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 588 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 589 VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), 590 "Component iterator at invalid tuple id."); 591 VTK_ITER_ASSERT( 592 comp >= 0 && comp <= numComps.value, "Component iterator at invalid component id."); 593 } 594 595 VTK_ITER_INLINE 596 ComponentIterator(const ComponentIterator& o) noexcept = default; 597 598 VTK_ITER_INLINE 599 ComponentIterator& operator=(const ComponentIterator& o) noexcept 600 { 601 this->Ref.CopyReference(o.Ref); 602 return *this; 603 } 604 605 VTK_ITER_INLINE 606 ComponentIterator& operator++() noexcept // prefix 607 { 608 ++this->Ref.ComponentId; 609 VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value, 610 "Component iterator at invalid component id."); 611 return *this; 612 } 613 614 VTK_ITER_INLINE 615 ComponentIterator operator++(int) noexcept // postfix 616 { 617 return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId, 618 this->Ref.ComponentId++ }; 619 } 620 621 VTK_ITER_INLINE 622 ComponentIterator& operator--() noexcept // prefix 623 { 624 --this->Ref.ComponentId; 625 VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value, 626 "Component iterator at invalid component id."); 627 return *this; 628 } 629 630 VTK_ITER_INLINE 631 ComponentIterator operator--(int) noexcept // postfix 632 { 633 return ComponentIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId, 634 this->Ref.ComponentId-- }; 635 } 636 637 VTK_ITER_INLINE 638 reference operator[](difference_type i) const noexcept 639 { 640 return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId, 641 this->Ref.ComponentId + i }; 642 } 643 644 VTK_ITER_INLINE 645 reference operator*() const noexcept { return this->Ref; } 646 647 VTK_ITER_INLINE 648 const pointer& operator->() const noexcept { return this->Ref; } 649 650 #define VTK_TMP_MAKE_OPERATOR(OP) \ 651 friend VTK_ITER_INLINE bool operator OP( \ 652 const ComponentIterator& lhs, const ComponentIterator& rhs) noexcept \ 653 { \ 654 VTK_ITER_ASSERT( \ 655 lhs.GetArray() == rhs.GetArray(), "Mismatched arrays in iterator comparison."); \ 656 VTK_ITER_ASSERT( \ 657 lhs.GetTupleId() == rhs.GetTupleId(), "Mismatched tuple ids in iterator comparison."); \ 658 VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \ 659 VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \ 660 return lhs.GetComponentId() OP rhs.GetComponentId(); \ 661 } 662 663 VTK_TMP_MAKE_OPERATOR(==) 664 VTK_TMP_MAKE_OPERATOR(!=) 665 VTK_TMP_MAKE_OPERATOR(<) 666 VTK_TMP_MAKE_OPERATOR(>) 667 VTK_TMP_MAKE_OPERATOR(<=) 668 VTK_TMP_MAKE_OPERATOR(>=) 669 670 #undef VTK_TMP_MAKE_OPERATOR 671 672 VTK_ITER_INLINE 673 ComponentIterator& operator+=(difference_type offset) noexcept 674 { 675 this->Ref.ComponentId += offset; 676 VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value, 677 "Component iterator at invalid component id."); 678 return *this; 679 } 680 681 friend VTK_ITER_INLINE ComponentIterator operator+( 682 const ComponentIterator& it, difference_type offset) noexcept 683 { 684 return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(), 685 it.GetComponentId() + offset }; 686 } 687 688 friend VTK_ITER_INLINE ComponentIterator operator+( 689 difference_type offset, const ComponentIterator& it) noexcept 690 { 691 return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(), 692 it.GetComponentId() + offset }; 693 } 694 695 VTK_ITER_INLINE 696 ComponentIterator& operator-=(difference_type offset) noexcept 697 { 698 this->Ref.ComponentId -= offset; 699 VTK_ITER_ASSERT(this->Ref.ComponentId >= 0 && this->Ref.ComponentId <= this->Ref.NumComps.value, 700 "Component iterator at invalid component id."); 701 return *this; 702 } 703 704 friend VTK_ITER_INLINE ComponentIterator operator-( 705 const ComponentIterator& it, difference_type offset) noexcept 706 { 707 return ComponentIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId(), 708 it.GetComponentId() - offset }; 709 } 710 711 friend VTK_ITER_INLINE difference_type operator-( 712 const ComponentIterator& it1, const ComponentIterator& it2) noexcept 713 { 714 VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(), 715 "Cannot do math with component iterators from different " 716 "arrays."); 717 VTK_ITER_ASSERT(it1.GetTupleId() == it2.GetTupleId(), 718 "Cannot do math with component iterators from different " 719 "tuples."); 720 return it1.GetComponentId() - it2.GetComponentId(); 721 } 722 723 friend VTK_ITER_INLINE void swap(ComponentIterator& lhs, ComponentIterator& rhs) noexcept 724 { 725 // Different arrays may use different iterator implementations. 726 VTK_ITER_ASSERT( 727 lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays."); 728 729 using std::swap; 730 swap(lhs.GetTupleId(), rhs.GetTupleId()); 731 swap(lhs.GetComponentId(), rhs.GetComponentId()); 732 } 733 734 friend struct ConstComponentIterator<ArrayType, TupleSize>; 735 736 protected: 737 // Needed for access from friend functions. We could just store the array 738 // and ID here instead of the ref, but meh. 739 ArrayType* GetArray() const noexcept { return this->Ref.Array; } 740 TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; } 741 const TupleIdType& GetTupleId() const noexcept { return this->Ref.TupleId; } 742 ComponentIdType& GetComponentId() noexcept { return this->Ref.ComponentId; } 743 const ComponentIdType& GetComponentId() const noexcept { return this->Ref.ComponentId; } 744 NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; } 745 const NumCompsType& GetNumComps() const noexcept { return this->Ref.NumComps; } 746 747 ComponentReference<ArrayType, TupleSize> Ref; 748 }; 749 750 //------------------------------------------------------------------------------ 751 // Const tuple reference 752 template <typename ArrayType, ComponentIdType TupleSize> 753 struct ConstTupleReference 754 { 755 private: 756 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 757 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 758 759 using NumCompsType = GenericTupleSize<TupleSize>; 760 using APIType = GetAPIType<ArrayType>; 761 762 public: 763 using size_type = ComponentIdType; 764 using value_type = APIType; 765 using iterator = ConstComponentIterator<ArrayType, TupleSize>; 766 using const_iterator = ConstComponentIterator<ArrayType, TupleSize>; 767 using const_reference = ConstComponentReference<ArrayType, TupleSize>; 768 769 VTK_ITER_INLINE 770 ConstTupleReference() noexcept 771 : Array(nullptr) 772 , TupleId(0) 773 { 774 } 775 776 VTK_ITER_INLINE 777 ConstTupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept 778 : Array(array) 779 , NumComps(numComps) 780 , TupleId(tupleId) 781 { 782 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 783 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 784 VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), 785 "Const tuple reference at invalid tuple id."); 786 } 787 788 VTK_ITER_INLINE 789 ConstTupleReference(const TupleReference<ArrayType, TupleSize>& o) noexcept 790 : Array{ o.Array } 791 , NumComps{ o.NumComps } 792 , TupleId{ o.TupleId } 793 { 794 } 795 796 VTK_ITER_INLINE 797 ConstTupleReference(const ConstTupleReference&) noexcept = default; 798 VTK_ITER_INLINE 799 ConstTupleReference(ConstTupleReference&&) noexcept = default; 800 801 // Allow this type to masquerade as a pointer, so that tupleIiter->foo works. 802 VTK_ITER_INLINE 803 ConstTupleReference* operator->() noexcept { return this; } 804 VTK_ITER_INLINE 805 const ConstTupleReference* operator->() const noexcept { return this; } 806 807 // Caller must ensure that there are size() elements in array. 808 VTK_ITER_INLINE 809 void GetTuple(APIType* tuple) const noexcept 810 { 811 VTK_ITER_ASSUME(this->NumComps.value > 0); 812 VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value); 813 vtkDataArrayAccessor<ArrayType> acc{ this->Array }; 814 acc.Get(this->TupleId, tuple); 815 } 816 817 // skips some runtime checks when both sizes are fixed: 818 template <typename OArrayType, ComponentIdType OSize> 819 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, bool> operator==( 820 const TupleReference<OArrayType, OSize>& other) const noexcept 821 { 822 // Check that types are convertible: 823 using OAPIType = GetAPIType<OArrayType>; 824 static_assert( 825 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 826 827 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 828 static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes."); 829 830 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 831 } 832 833 // Needs a runtime check: 834 template <typename OArrayType, ComponentIdType OSize> 835 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, bool> operator==( 836 const TupleReference<OArrayType, OSize>& other) const noexcept 837 { 838 // Check that types are convertible: 839 using OAPIType = GetAPIType<OArrayType>; 840 static_assert( 841 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 842 843 VTK_ITER_ASSERT( 844 other.size() == this->NumComps.value, "Cannot compare tuples with different sizes."); 845 846 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 847 } 848 849 // skips some runtime checks when both sizes are fixed: 850 template <typename OArrayType, ComponentIdType OSize> 851 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, bool> operator==( 852 const ConstTupleReference<OArrayType, OSize>& other) const noexcept 853 { 854 // Check that types are convertible: 855 using OAPIType = GetAPIType<OArrayType>; 856 static_assert( 857 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 858 859 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 860 static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes."); 861 862 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 863 } 864 865 // Needs a runtime check: 866 template <typename OArrayType, ComponentIdType OSize> 867 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, bool> operator==( 868 const ConstTupleReference<OArrayType, OSize>& other) const noexcept 869 { 870 // Check that types are convertible: 871 using OAPIType = GetAPIType<OArrayType>; 872 static_assert( 873 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 874 875 VTK_ITER_ASSERT( 876 other.size() == this->NumComps.value, "Cannot compare tuples with different sizes."); 877 878 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 879 } 880 881 template <typename OArrayType, ComponentIdType OSize> 882 VTK_ITER_INLINE bool operator!=(const TupleReference<OArrayType, OSize>& o) const noexcept 883 { 884 return !(*this == o); 885 } 886 887 template <typename OArrayT, ComponentIdType OSize> 888 VTK_ITER_INLINE bool operator!=(const ConstTupleReference<OArrayT, OSize>& o) const noexcept 889 { 890 return !(*this == o); 891 } 892 893 VTK_ITER_INLINE 894 const_reference operator[](size_type i) const noexcept 895 { 896 return const_reference{ this->Array, this->NumComps, this->TupleId, i }; 897 } 898 899 VTK_ITER_INLINE 900 size_type size() const noexcept { return this->NumComps.value; } 901 902 VTK_ITER_INLINE 903 const_iterator begin() const noexcept { return this->NewConstIterator(0); } 904 VTK_ITER_INLINE 905 const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); } 906 907 VTK_ITER_INLINE 908 const_iterator cbegin() const noexcept { return this->NewConstIterator(0); } 909 VTK_ITER_INLINE 910 const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); } 911 912 friend struct ConstTupleIterator<ArrayType, TupleSize>; 913 914 protected: 915 // Intentionally hidden: 916 VTK_ITER_INLINE 917 ConstTupleReference& operator=(const ConstTupleReference&) noexcept = default; 918 919 VTK_ITER_INLINE 920 const_iterator NewConstIterator(ComponentIdType comp) const noexcept 921 { 922 VTK_ITER_ASSUME(this->NumComps.value > 0); 923 return const_iterator{ this->Array, this->NumComps, this->TupleId, comp }; 924 } 925 926 VTK_ITER_INLINE 927 void CopyReference(const ConstTupleReference& o) noexcept 928 { 929 // Must use same array, other array types may use different implementations. 930 VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays."); 931 this->NumComps = o.NumComps; 932 this->TupleId = o.TupleId; 933 } 934 935 mutable ArrayType* Array; 936 NumCompsType NumComps; 937 TupleIdType TupleId; 938 }; 939 940 //------------------------------------------------------------------------------ 941 // Tuple reference 942 template <typename ArrayType, ComponentIdType TupleSize> 943 struct TupleReference 944 { 945 private: 946 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 947 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 948 949 using NumCompsType = GenericTupleSize<TupleSize>; 950 using APIType = GetAPIType<ArrayType>; 951 952 public: 953 using size_type = ComponentIdType; 954 using value_type = APIType; 955 using iterator = ComponentIterator<ArrayType, TupleSize>; 956 using const_iterator = ConstComponentIterator<ArrayType, TupleSize>; 957 using reference = ComponentReference<ArrayType, TupleSize>; 958 using const_reference = ConstComponentReference<ArrayType, TupleSize>; 959 960 VTK_ITER_INLINE 961 TupleReference() noexcept 962 : Array(nullptr) 963 , TupleId(0) 964 { 965 } 966 967 VTK_ITER_INLINE 968 TupleReference(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept 969 : Array(array) 970 , NumComps(numComps) 971 , TupleId(tupleId) 972 { 973 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 974 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 975 VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), 976 "Tuple reference at invalid tuple id."); 977 } 978 979 VTK_ITER_INLINE 980 TupleReference(const TupleReference&) = default; 981 VTK_ITER_INLINE 982 TupleReference(TupleReference&&) = default; 983 984 // Allow this type to masquerade as a pointer, so that tupleIiter->foo works. 985 VTK_ITER_INLINE 986 TupleReference* operator->() noexcept { return this; } 987 VTK_ITER_INLINE 988 const TupleReference* operator->() const noexcept { return this; } 989 990 // Caller must ensure that there are size() elements in array. 991 VTK_ITER_INLINE 992 void GetTuple(APIType* tuple) const noexcept 993 { 994 VTK_ITER_ASSUME(this->NumComps.value > 0); 995 VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value); 996 vtkDataArrayAccessor<ArrayType> acc{ this->Array }; 997 acc.Get(this->TupleId, tuple); 998 } 999 1000 // Caller must ensure that there are size() elements in array. 1001 VTK_ITER_INLINE 1002 void SetTuple(const APIType* tuple) noexcept 1003 { 1004 VTK_ITER_ASSUME(this->NumComps.value > 0); 1005 VTK_ITER_ASSUME(this->Array->GetNumberOfComponents() == this->NumComps.value); 1006 vtkDataArrayAccessor<ArrayType> acc{ this->Array }; 1007 acc.Set(this->TupleId, tuple); 1008 } 1009 1010 VTK_ITER_INLINE 1011 TupleReference& operator=(const TupleReference& other) noexcept 1012 { 1013 std::copy_n(other.cbegin(), this->NumComps.value, this->begin()); 1014 return *this; 1015 } 1016 1017 // skips some runtime checks when both sizes are fixed: 1018 template <typename OArrayType, ComponentIdType OSize> 1019 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, TupleReference&> operator=( 1020 const TupleReference<OArrayType, OSize>& other) noexcept 1021 { 1022 // Check that types are convertible: 1023 using OAPIType = GetAPIType<OArrayType>; 1024 static_assert( 1025 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples."); 1026 1027 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 1028 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes."); 1029 1030 std::copy_n(other.cbegin(), OSize, this->begin()); 1031 return *this; 1032 } 1033 1034 // Needs a runtime check: 1035 template <typename OArrayType, ComponentIdType OSize> 1036 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, TupleReference&> operator=( 1037 const TupleReference<OArrayType, OSize>& other) noexcept 1038 { 1039 // Check that types are convertible: 1040 using OAPIType = GetAPIType<OArrayType>; 1041 static_assert( 1042 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples."); 1043 1044 VTK_ITER_ASSERT( 1045 other.size() == this->NumComps.value, "Cannot assign tuples with different sizes."); 1046 1047 std::copy_n(other.cbegin(), this->NumComps.value, this->begin()); 1048 return *this; 1049 } 1050 1051 // skips some runtime checks when both sizes are fixed: 1052 template <typename OArrayType, ComponentIdType OSize> 1053 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, TupleReference&> operator=( 1054 const ConstTupleReference<OArrayType, OSize>& other) noexcept 1055 { 1056 // Check that types are convertible: 1057 using OAPIType = GetAPIType<OArrayType>; 1058 static_assert( 1059 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples."); 1060 1061 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 1062 static_assert(TupleSize == OSize, "Cannot assign tuples with different sizes."); 1063 1064 std::copy_n(other.cbegin(), OSize, this->begin()); 1065 return *this; 1066 } 1067 1068 // Needs a runtime check: 1069 template <typename OArrayType, ComponentIdType OSize> 1070 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, TupleReference&> operator=( 1071 const ConstTupleReference<OArrayType, OSize>& other) noexcept 1072 { 1073 // Check that types are convertible: 1074 using OAPIType = GetAPIType<OArrayType>; 1075 static_assert( 1076 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when assigning tuples."); 1077 1078 VTK_ITER_ASSERT( 1079 other.size() == this->NumComps.value, "Cannot assign tuples with different sizes."); 1080 1081 std::copy_n(other.cbegin(), this->NumComps.value, this->begin()); 1082 return *this; 1083 } 1084 1085 // skips some runtime checks when both sizes are fixed: 1086 template <typename OArrayType, ComponentIdType OSize> 1087 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, bool> operator==( 1088 const TupleReference<OArrayType, OSize>& other) const noexcept 1089 { 1090 // Check that types are convertible: 1091 using OAPIType = GetAPIType<OArrayType>; 1092 static_assert( 1093 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 1094 1095 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 1096 static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes."); 1097 1098 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 1099 } 1100 1101 // Needs a runtime check: 1102 template <typename OArrayType, ComponentIdType OSize> 1103 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, bool> operator==( 1104 const TupleReference<OArrayType, OSize>& other) const noexcept 1105 { 1106 // Check that types are convertible: 1107 using OAPIType = GetAPIType<OArrayType>; 1108 static_assert( 1109 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 1110 1111 VTK_ITER_ASSERT( 1112 other.size() == this->NumComps.value, "Cannot compare tuples with different sizes."); 1113 1114 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 1115 } 1116 1117 // skips some runtime checks when both sizes are fixed: 1118 template <typename OArrayType, ComponentIdType OSize> 1119 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, bool> operator==( 1120 const ConstTupleReference<OArrayType, OSize>& other) const noexcept 1121 { 1122 // Check that types are convertible: 1123 using OAPIType = GetAPIType<OArrayType>; 1124 static_assert( 1125 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 1126 1127 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 1128 static_assert(TupleSize == OSize, "Cannot compare tuples with different sizes."); 1129 1130 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 1131 } 1132 1133 // Needs a runtime check: 1134 template <typename OArrayType, ComponentIdType OSize> 1135 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, bool> operator==( 1136 const ConstTupleReference<OArrayType, OSize>& other) const noexcept 1137 { 1138 // Check that types are convertible: 1139 using OAPIType = GetAPIType<OArrayType>; 1140 static_assert( 1141 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when comparing tuples."); 1142 1143 VTK_ITER_ASSERT( 1144 other.size() == this->NumComps.value, "Cannot compare tuples with different sizes."); 1145 1146 return std::equal(this->cbegin(), this->cend(), other.cbegin()); 1147 } 1148 1149 template <typename OArrayType, ComponentIdType OSize> 1150 VTK_ITER_INLINE bool operator!=(const TupleReference<OArrayType, OSize>& o) const noexcept 1151 { 1152 return !(*this == o); 1153 } 1154 1155 template <typename OArray, ComponentIdType OSize> 1156 VTK_ITER_INLINE bool operator!=(const ConstTupleReference<OArray, OSize>& o) const noexcept 1157 { 1158 return !(*this == o); 1159 } 1160 1161 // skips some runtime checks: 1162 template <typename OArrayType, ComponentIdType OSize> 1163 VTK_ITER_INLINE EnableIfStaticTupleSizes<TupleSize, OSize, void> swap( 1164 TupleReference<OArrayType, OSize> other) noexcept 1165 { 1166 // Check that types are convertible: 1167 using OAPIType = GetAPIType<OArrayType>; 1168 static_assert( 1169 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples."); 1170 1171 // SFINAE guarantees that the tuple sizes are not dynamic in this overload: 1172 static_assert(TupleSize == OSize, "Cannot swap tuples with different sizes."); 1173 1174 std::swap_ranges(this->begin(), this->end(), other.begin()); 1175 } 1176 1177 // Needs a runtime check: 1178 template <typename OArrayType, ComponentIdType OSize> 1179 VTK_ITER_INLINE EnableIfEitherTupleSizeIsDynamic<TupleSize, OSize, void> swap( 1180 TupleReference<OArrayType, OSize> other) noexcept 1181 { 1182 // Check that types are convertible: 1183 using OAPIType = GetAPIType<OArrayType>; 1184 static_assert( 1185 (std::is_convertible<OAPIType, APIType>{}), "Incompatible types when swapping tuples."); 1186 1187 VTK_ITER_ASSERT( 1188 other.size() == this->NumComps.value, "Cannot swap tuples with different sizes."); 1189 1190 std::swap_ranges(this->begin(), this->end(), other.begin()); 1191 } 1192 1193 friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference b) noexcept { a.swap(b); } 1194 1195 template <typename OArray, ComponentIdType OSize> 1196 friend VTK_ITER_INLINE void swap(TupleReference a, TupleReference<OArray, OSize> b) noexcept 1197 { 1198 a.swap(b); 1199 } 1200 1201 VTK_ITER_INLINE 1202 reference operator[](size_type i) noexcept 1203 { 1204 return reference{ this->Array, this->NumComps, this->TupleId, i }; 1205 } 1206 1207 VTK_ITER_INLINE 1208 const_reference operator[](size_type i) const noexcept 1209 { 1210 // Let the reference type do the lookup during implicit conversion. 1211 return const_reference{ this->Array, this->NumComps, this->TupleId, i }; 1212 } 1213 1214 VTK_ITER_INLINE 1215 void fill(const value_type& v) noexcept { std::fill(this->begin(), this->end(), v); } 1216 1217 VTK_ITER_INLINE 1218 size_type size() const noexcept { return this->NumComps.value; } 1219 1220 VTK_ITER_INLINE 1221 iterator begin() noexcept { return this->NewIterator(0); } 1222 VTK_ITER_INLINE 1223 iterator end() noexcept { return this->NewIterator(this->NumComps.value); } 1224 1225 VTK_ITER_INLINE 1226 const_iterator begin() const noexcept { return this->NewConstIterator(0); } 1227 VTK_ITER_INLINE 1228 const_iterator end() const noexcept { return this->NewConstIterator(this->NumComps.value); } 1229 1230 VTK_ITER_INLINE 1231 const_iterator cbegin() const noexcept { return this->NewConstIterator(0); } 1232 VTK_ITER_INLINE 1233 const_iterator cend() const noexcept { return this->NewConstIterator(this->NumComps.value); } 1234 1235 friend struct ConstTupleReference<ArrayType, TupleSize>; 1236 friend struct TupleIterator<ArrayType, TupleSize>; 1237 1238 protected: 1239 VTK_ITER_INLINE 1240 iterator NewIterator(ComponentIdType comp) const noexcept 1241 { 1242 VTK_ITER_ASSUME(this->NumComps.value > 0); 1243 return iterator{ this->Array, this->NumComps, this->TupleId, comp }; 1244 } 1245 1246 VTK_ITER_INLINE 1247 const_iterator NewConstIterator(ComponentIdType comp) const noexcept 1248 { 1249 VTK_ITER_ASSUME(this->NumComps.value > 0); 1250 return const_iterator{ this->Array, this->NumComps, this->TupleId, comp }; 1251 } 1252 1253 VTK_ITER_INLINE 1254 void CopyReference(const TupleReference& o) noexcept 1255 { 1256 // Must use same array, other array types may use different implementations. 1257 VTK_ITER_ASSERT(this->Array == o.Array, "Cannot copy reference objects between arrays."); 1258 this->NumComps = o.NumComps; 1259 this->TupleId = o.TupleId; 1260 } 1261 1262 mutable ArrayType* Array; 1263 NumCompsType NumComps; 1264 TupleIdType TupleId; 1265 }; 1266 1267 //------------------------------------------------------------------------------ 1268 // Const tuple iterator 1269 template <typename ArrayType, ComponentIdType TupleSize> 1270 struct ConstTupleIterator 1271 { 1272 private: 1273 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 1274 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 1275 1276 using NumCompsType = GenericTupleSize<TupleSize>; 1277 1278 public: 1279 using iterator_category = std::random_access_iterator_tag; 1280 using value_type = ConstTupleReference<ArrayType, TupleSize>; 1281 using difference_type = TupleIdType; 1282 using pointer = ConstTupleReference<ArrayType, TupleSize>; 1283 using reference = ConstTupleReference<ArrayType, TupleSize>; 1284 1285 VTK_ITER_INLINE 1286 ConstTupleIterator() noexcept = default; 1287 1288 VTK_ITER_INLINE 1289 ConstTupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept 1290 : Ref(array, numComps, tupleId) 1291 { 1292 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 1293 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 1294 VTK_ITER_ASSERT(tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), 1295 "Const tuple iterator at invalid tuple id."); 1296 } 1297 1298 VTK_ITER_INLINE 1299 ConstTupleIterator(const TupleIterator<ArrayType, TupleSize>& o) noexcept 1300 : Ref{ o.Ref } 1301 { 1302 } 1303 1304 VTK_ITER_INLINE 1305 ConstTupleIterator(const ConstTupleIterator& o) noexcept = default; 1306 VTK_ITER_INLINE 1307 ConstTupleIterator& operator=(const ConstTupleIterator& o) noexcept 1308 { 1309 this->Ref.CopyReference(o.Ref); 1310 return *this; 1311 } 1312 1313 VTK_ITER_INLINE 1314 ConstTupleIterator& operator++() noexcept // prefix 1315 { 1316 ++this->Ref.TupleId; 1317 VTK_ITER_ASSERT( 1318 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1319 "Const tuple iterator at invalid component id."); 1320 return *this; 1321 } 1322 1323 VTK_ITER_INLINE 1324 ConstTupleIterator operator++(int) noexcept // postfix 1325 { 1326 return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ }; 1327 } 1328 1329 VTK_ITER_INLINE 1330 ConstTupleIterator& operator--() noexcept // prefix 1331 { 1332 --this->Ref.TupleId; 1333 VTK_ITER_ASSERT( 1334 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1335 "Const tuple iterator at invalid component id."); 1336 return *this; 1337 } 1338 1339 VTK_ITER_INLINE 1340 ConstTupleIterator operator--(int) noexcept // postfix 1341 { 1342 return ConstTupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- }; 1343 } 1344 1345 VTK_ITER_INLINE 1346 reference operator[](difference_type i) noexcept 1347 { 1348 return reference{ this->GetArray(), this->GetNumComps(), this->GetTupleId() + i }; 1349 } 1350 1351 VTK_ITER_INLINE 1352 reference operator*() noexcept { return this->Ref; } 1353 1354 VTK_ITER_INLINE 1355 pointer operator->() noexcept { return this->Ref; } 1356 1357 #define VTK_TMP_MAKE_OPERATOR(OP) \ 1358 friend VTK_ITER_INLINE bool operator OP( \ 1359 const ConstTupleIterator& lhs, const ConstTupleIterator& rhs) noexcept \ 1360 { \ 1361 VTK_ITER_ASSERT( \ 1362 lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \ 1363 VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \ 1364 VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \ 1365 return lhs.GetTupleId() OP rhs.GetTupleId(); \ 1366 } 1367 1368 VTK_TMP_MAKE_OPERATOR(==) 1369 VTK_TMP_MAKE_OPERATOR(!=) 1370 VTK_TMP_MAKE_OPERATOR(<) 1371 VTK_TMP_MAKE_OPERATOR(>) 1372 VTK_TMP_MAKE_OPERATOR(<=) 1373 VTK_TMP_MAKE_OPERATOR(>=) 1374 1375 #undef VTK_TMP_MAKE_OPERATOR 1376 1377 VTK_ITER_INLINE 1378 ConstTupleIterator& operator+=(difference_type offset) noexcept 1379 { 1380 this->Ref.TupleId += offset; 1381 VTK_ITER_ASSERT( 1382 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1383 "Const tuple iterator at invalid component id."); 1384 return *this; 1385 } 1386 1387 friend VTK_ITER_INLINE ConstTupleIterator operator+( 1388 const ConstTupleIterator& it, difference_type offset) noexcept 1389 { 1390 return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset }; 1391 } 1392 1393 friend VTK_ITER_INLINE ConstTupleIterator operator+( 1394 difference_type offset, const ConstTupleIterator& it) noexcept 1395 { 1396 return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset }; 1397 } 1398 1399 VTK_ITER_INLINE 1400 ConstTupleIterator& operator-=(difference_type offset) noexcept 1401 { 1402 this->Ref.TupleId -= offset; 1403 VTK_ITER_ASSERT( 1404 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1405 "Const tuple iterator at invalid component id."); 1406 return *this; 1407 } 1408 1409 friend VTK_ITER_INLINE ConstTupleIterator operator-( 1410 const ConstTupleIterator& it, difference_type offset) noexcept 1411 { 1412 return ConstTupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset }; 1413 } 1414 1415 friend VTK_ITER_INLINE difference_type operator-( 1416 const ConstTupleIterator& it1, const ConstTupleIterator& it2) noexcept 1417 { 1418 VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(), 1419 "Cannot do math with tuple iterators from different " 1420 "arrays."); 1421 return it1.GetTupleId() - it2.GetTupleId(); 1422 } 1423 1424 friend VTK_ITER_INLINE void swap(ConstTupleIterator& lhs, ConstTupleIterator& rhs) noexcept 1425 { 1426 // Different arrays may use different iterator implementations. 1427 VTK_ITER_ASSERT( 1428 lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays."); 1429 1430 using std::swap; 1431 swap(lhs.GetTupleId(), rhs.GetTupleId()); 1432 } 1433 1434 private: 1435 VTK_ITER_INLINE 1436 ArrayType* GetArray() const noexcept { return this->Ref.Array; } 1437 VTK_ITER_INLINE 1438 ArrayType*& GetArray() noexcept { return this->Ref.Array; } 1439 VTK_ITER_INLINE 1440 NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; } 1441 VTK_ITER_INLINE 1442 NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; } 1443 VTK_ITER_INLINE 1444 TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; } 1445 VTK_ITER_INLINE 1446 TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; } 1447 1448 ConstTupleReference<ArrayType, TupleSize> Ref; 1449 }; 1450 1451 //------------------------------------------------------------------------------ 1452 // Tuple iterator 1453 template <typename ArrayType, ComponentIdType TupleSize> 1454 struct TupleIterator 1455 { 1456 private: 1457 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 1458 static_assert(IsVtkDataArray<ArrayType>::value, "Invalid array type."); 1459 1460 using NumCompsType = GenericTupleSize<TupleSize>; 1461 1462 public: 1463 using iterator_category = std::random_access_iterator_tag; 1464 using value_type = TupleReference<ArrayType, TupleSize>; 1465 using difference_type = TupleIdType; 1466 using pointer = TupleReference<ArrayType, TupleSize>; 1467 using reference = TupleReference<ArrayType, TupleSize>; 1468 1469 VTK_ITER_INLINE 1470 TupleIterator() noexcept = default; 1471 1472 VTK_ITER_INLINE 1473 TupleIterator(ArrayType* array, NumCompsType numComps, TupleIdType tupleId) noexcept 1474 : Ref(array, numComps, tupleId) 1475 { 1476 VTK_ITER_ASSERT(array != nullptr, "Invalid array."); 1477 VTK_ITER_ASSERT(numComps.value > 0, "Invalid number of components."); 1478 VTK_ITER_ASSERT( 1479 tupleId >= 0 && tupleId <= array->GetNumberOfTuples(), "Tuple iterator at invalid tuple id."); 1480 } 1481 1482 VTK_ITER_INLINE 1483 TupleIterator(const TupleIterator& o) noexcept = default; 1484 1485 VTK_ITER_INLINE 1486 TupleIterator& operator=(const TupleIterator& o) noexcept 1487 { 1488 this->Ref.CopyReference(o.Ref); 1489 return *this; 1490 } 1491 1492 VTK_ITER_INLINE 1493 TupleIterator& operator++() noexcept // prefix 1494 { 1495 ++this->Ref.TupleId; 1496 VTK_ITER_ASSERT( 1497 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1498 "Tuple iterator at invalid component id."); 1499 return *this; 1500 } 1501 1502 VTK_ITER_INLINE 1503 TupleIterator operator++(int) noexcept // postfix 1504 { 1505 return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId++ }; 1506 } 1507 1508 VTK_ITER_INLINE 1509 TupleIterator& operator--() noexcept // prefix 1510 { 1511 --this->Ref.TupleId; 1512 VTK_ITER_ASSERT( 1513 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1514 "Tuple iterator at invalid component id."); 1515 return *this; 1516 } 1517 1518 VTK_ITER_INLINE 1519 TupleIterator operator--(int) noexcept // postfix 1520 { 1521 return TupleIterator{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId-- }; 1522 } 1523 1524 VTK_ITER_INLINE 1525 reference operator[](difference_type i) noexcept 1526 { 1527 return reference{ this->Ref.Array, this->Ref.NumComps, this->Ref.TupleId + i }; 1528 } 1529 1530 VTK_ITER_INLINE 1531 reference operator*() noexcept { return this->Ref; } 1532 1533 VTK_ITER_INLINE 1534 pointer& operator->() noexcept { return this->Ref; } 1535 1536 #define VTK_TMP_MAKE_OPERATOR(OP) \ 1537 friend VTK_ITER_INLINE bool operator OP( \ 1538 const TupleIterator& lhs, const TupleIterator& rhs) noexcept \ 1539 { \ 1540 VTK_ITER_ASSERT( \ 1541 lhs.GetArray() == rhs.GetArray(), "Cannot compare iterators from different arrays."); \ 1542 VTK_ITER_ASSUME(lhs.GetNumComps().value > 0); \ 1543 VTK_ITER_ASSUME(lhs.GetNumComps().value == rhs.GetNumComps().value); \ 1544 return lhs.GetTupleId() OP rhs.GetTupleId(); \ 1545 } 1546 1547 VTK_TMP_MAKE_OPERATOR(==) 1548 VTK_TMP_MAKE_OPERATOR(!=) 1549 VTK_TMP_MAKE_OPERATOR(<) 1550 VTK_TMP_MAKE_OPERATOR(>) 1551 VTK_TMP_MAKE_OPERATOR(<=) 1552 VTK_TMP_MAKE_OPERATOR(>=) 1553 1554 #undef VTK_TMP_MAKE_OPERATOR 1555 1556 VTK_ITER_INLINE 1557 TupleIterator& operator+=(difference_type offset) noexcept 1558 { 1559 this->Ref.TupleId += offset; 1560 VTK_ITER_ASSERT( 1561 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1562 "Tuple iterator at invalid component id."); 1563 return *this; 1564 } 1565 1566 friend VTK_ITER_INLINE TupleIterator operator+( 1567 const TupleIterator& it, difference_type offset) noexcept 1568 { 1569 return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset }; 1570 } 1571 1572 friend VTK_ITER_INLINE TupleIterator operator+( 1573 difference_type offset, const TupleIterator& it) noexcept 1574 { 1575 return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() + offset }; 1576 } 1577 1578 VTK_ITER_INLINE 1579 TupleIterator& operator-=(difference_type offset) noexcept 1580 { 1581 this->Ref.TupleId -= offset; 1582 VTK_ITER_ASSERT( 1583 this->Ref.TupleId >= 0 && this->Ref.TupleId <= this->Ref.Array->GetNumberOfTuples(), 1584 "Tuple iterator at invalid component id."); 1585 return *this; 1586 } 1587 1588 friend VTK_ITER_INLINE TupleIterator operator-( 1589 const TupleIterator& it, difference_type offset) noexcept 1590 { 1591 return TupleIterator{ it.GetArray(), it.GetNumComps(), it.GetTupleId() - offset }; 1592 } 1593 1594 friend VTK_ITER_INLINE difference_type operator-( 1595 const TupleIterator& it1, const TupleIterator& it2) noexcept 1596 { 1597 VTK_ITER_ASSERT(it1.GetArray() == it2.GetArray(), 1598 "Cannot do math with tuple iterators from different " 1599 "arrays."); 1600 return it1.GetTupleId() - it2.GetTupleId(); 1601 } 1602 1603 friend VTK_ITER_INLINE void swap(TupleIterator& lhs, TupleIterator& rhs) noexcept 1604 { 1605 // Different arrays may use different iterator implementations. 1606 VTK_ITER_ASSERT( 1607 lhs.GetArray() == rhs.GetArray(), "Cannot swap iterators from different arrays."); 1608 1609 using std::swap; 1610 swap(lhs.GetTupleId(), rhs.GetTupleId()); 1611 } 1612 1613 friend struct ConstTupleIterator<ArrayType, TupleSize>; 1614 friend struct ConstTupleReference<ArrayType, TupleSize>; 1615 1616 protected: 1617 VTK_ITER_INLINE 1618 ArrayType* GetArray() const noexcept { return this->Ref.Array; } 1619 VTK_ITER_INLINE 1620 ArrayType*& GetArray() noexcept { return this->Ref.Array; } 1621 VTK_ITER_INLINE 1622 NumCompsType GetNumComps() const noexcept { return this->Ref.NumComps; } 1623 VTK_ITER_INLINE 1624 NumCompsType& GetNumComps() noexcept { return this->Ref.NumComps; } 1625 VTK_ITER_INLINE 1626 TupleIdType GetTupleId() const noexcept { return this->Ref.TupleId; } 1627 VTK_ITER_INLINE 1628 TupleIdType& GetTupleId() noexcept { return this->Ref.TupleId; } 1629 1630 TupleReference<ArrayType, TupleSize> Ref; 1631 }; 1632 1633 //------------------------------------------------------------------------------ 1634 // Tuple range 1635 template <typename ArrayTypeT, ComponentIdType TupleSize> 1636 struct TupleRange 1637 { 1638 private: 1639 using NumCompsType = GenericTupleSize<TupleSize>; 1640 static_assert(IsValidTupleSize<TupleSize>::value, "Invalid tuple size."); 1641 static_assert(IsVtkDataArray<ArrayTypeT>::value, "Invalid array type."); 1642 1643 public: 1644 using ArrayType = ArrayTypeT; 1645 using APIType = GetAPIType<ArrayType>; 1646 using TupleIteratorType = TupleIterator<ArrayType, TupleSize>; 1647 using ConstTupleIteratorType = ConstTupleIterator<ArrayType, TupleSize>; 1648 using TupleReferenceType = TupleReference<ArrayType, TupleSize>; 1649 using ConstTupleReferenceType = ConstTupleReference<ArrayType, TupleSize>; 1650 using ComponentIteratorType = ComponentIterator<ArrayType, TupleSize>; 1651 using ConstComponentIteratorType = ConstComponentIterator<ArrayType, TupleSize>; 1652 using ComponentReferenceType = ComponentReference<ArrayType, TupleSize>; 1653 using ConstComponentReferenceType = ConstComponentReference<ArrayType, TupleSize>; 1654 using ComponentType = APIType; 1655 1656 // May be DynamicTupleSize, or the actual tuple size. 1657 constexpr static ComponentIdType TupleSizeTag = TupleSize; 1658 1659 using size_type = TupleIdType; 1660 using iterator = TupleIteratorType; 1661 using const_iterator = ConstTupleIteratorType; 1662 using reference = TupleReferenceType; 1663 using const_reference = ConstTupleReferenceType; 1664 1665 VTK_ITER_INLINE 1666 TupleRange() noexcept = default; 1667 1668 VTK_ITER_INLINE 1669 TupleRange(ArrayType* arr, TupleIdType beginTuple, TupleIdType endTuple) noexcept 1670 : Array(arr) 1671 , NumComps(arr) 1672 , BeginTuple(beginTuple) 1673 , EndTuple(endTuple) 1674 { 1675 assert(this->Array); 1676 assert(beginTuple >= 0 && beginTuple <= endTuple); 1677 assert(endTuple >= 0 && endTuple <= this->Array->GetNumberOfTuples()); 1678 } 1679 1680 VTK_ITER_INLINE 1681 TupleRange GetSubRange(TupleIdType beginTuple = 0, TupleIdType endTuple = -1) const noexcept 1682 { 1683 const TupleIdType realBegin = this->BeginTuple + beginTuple; 1684 const TupleIdType realEnd = endTuple >= 0 ? this->BeginTuple + endTuple : this->EndTuple; 1685 1686 return TupleRange{ this->Array, realBegin, realEnd }; 1687 } 1688 1689 VTK_ITER_INLINE 1690 ArrayType* GetArray() const noexcept { return this->Array; } 1691 VTK_ITER_INLINE 1692 ComponentIdType GetTupleSize() const noexcept { return this->NumComps.value; } 1693 VTK_ITER_INLINE 1694 TupleIdType GetBeginTupleId() const noexcept { return this->BeginTuple; } 1695 VTK_ITER_INLINE 1696 TupleIdType GetEndTupleId() const noexcept { return this->EndTuple; } 1697 1698 VTK_ITER_INLINE 1699 size_type size() const noexcept { return this->EndTuple - this->BeginTuple; } 1700 1701 VTK_ITER_INLINE 1702 iterator begin() noexcept { return this->NewIter(this->BeginTuple); } 1703 VTK_ITER_INLINE 1704 iterator end() noexcept { return this->NewIter(this->EndTuple); } 1705 1706 VTK_ITER_INLINE 1707 const_iterator begin() const noexcept { return this->NewCIter(this->BeginTuple); } 1708 VTK_ITER_INLINE 1709 const_iterator end() const noexcept { return this->NewCIter(this->EndTuple); } 1710 1711 VTK_ITER_INLINE 1712 const_iterator cbegin() const noexcept { return this->NewCIter(this->BeginTuple); } 1713 VTK_ITER_INLINE 1714 const_iterator cend() const noexcept { return this->NewCIter(this->EndTuple); } 1715 1716 VTK_ITER_INLINE 1717 reference operator[](size_type i) noexcept 1718 { 1719 return reference{ this->Array, this->NumComps, this->BeginTuple + i }; 1720 } 1721 1722 VTK_ITER_INLINE 1723 const_reference operator[](size_type i) const noexcept 1724 { 1725 return const_reference{ this->Array, this->NumComps, this->BeginTuple + i }; 1726 } 1727 1728 private: 1729 VTK_ITER_INLINE 1730 iterator NewIter(TupleIdType t) const { return iterator{ this->Array, this->NumComps, t }; } 1731 1732 VTK_ITER_INLINE 1733 const_iterator NewCIter(TupleIdType t) const 1734 { 1735 return const_iterator{ this->Array, this->NumComps, t }; 1736 } 1737 1738 mutable ArrayType* Array{ nullptr }; 1739 NumCompsType NumComps{}; 1740 TupleIdType BeginTuple{ 0 }; 1741 TupleIdType EndTuple{ 0 }; 1742 }; 1743 1744 // Unimplemented, only used inside decltype in SelectTupleRange: 1745 template <typename ArrayType, ComponentIdType TupleSize> 1746 TupleRange<ArrayType, TupleSize> DeclareTupleRangeSpecialization(vtkDataArray*); 1747 1748 } // end namespace detail 1749 } // end namespace vtk 1750 1751 VTK_ITER_OPTIMIZE_END 1752 1753 #endif // __VTK_WRAP__ 1754 #endif // vtkDataArrayTupleRange_Generic_h 1755 1756 // VTK-HeaderTest-Exclude: vtkDataArrayTupleRange_Generic.h 1757