Changeset 5ce0659
- Timestamp:
- Nov 9, 2022, 5:18:48 PM (2 years ago)
- Branches:
- ADT, ast-experimental, master
- Children:
- 6a4ef0c
- Parents:
- 271a5d3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/Common/utility.h
r271a5d3 r5ce0659 452 452 453 453 // ----------------------------------------------------------------------------- 454 // Helper struct and function to support 455 // for ( val : group_iterate( container1, container2, ... ) ) {} 456 // syntax to have a for each that iterates multiple containers of the same length 457 // TODO: update to use variadic arguments 458 459 template< typename... > 460 struct group_iterate_t; 461 462 template< typename T1, typename T2 > 463 struct group_iterate_t<T1, T2> { 464 private: 465 std::tuple<T1, T2> args; 454 // Helper struct and function to support: 455 // for ( auto val : group_iterate( container1, container2, ... ) ) { ... } 456 // This iteraters through multiple containers of the same size. 457 458 template<typename... Args> 459 class group_iterate_t { 460 using Iterables = std::tuple<Args...>; 461 Iterables iterables; 462 463 template<size_t I> using Iter = decltype(std::get<I>(iterables).begin()); 464 template<size_t I> using Data = decltype(*std::get<I>(iterables).begin()); 465 template<typename> struct base_iterator; 466 467 template<std::size_t... Is> 468 struct base_iterator<std::integer_sequence<std::size_t, Is...>> { 469 using value_type = std::tuple< Data<Is>... >; 470 std::tuple<Iter<Is>...> iterators; 471 472 base_iterator( Iter<Is>... is ) : iterators( is... ) {} 473 base_iterator operator++() { 474 return base_iterator( ++std::get<Is>( iterators )... ); 475 } 476 bool operator!=( const base_iterator& other ) const { 477 return iterators != other.iterators; 478 } 479 value_type operator*() const { 480 return std::tie( *std::get<Is>( iterators )... ); 481 } 482 483 static base_iterator make_begin( Iterables & data ) { 484 return base_iterator( std::get<Is>( data ).begin()... ); 485 } 486 static base_iterator make_end( Iterables & data ) { 487 return base_iterator( std::get<Is>( data ).end()... ); 488 } 489 }; 490 466 491 public: 467 group_iterate_t( const T1 & v1, const T2 & v2 ) : args(v1, v2) {}; 468 469 typedef std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin())> value_type; 470 typedef decltype(std::get<0>(args).begin()) T1Iter; 471 typedef decltype(std::get<1>(args).begin()) T2Iter; 472 473 struct iterator { 474 typedef std::tuple<T1Iter, T2Iter> IterTuple; 475 IterTuple it; 476 iterator( T1Iter i1, T2Iter i2 ) : it( i1, i2 ) {} 477 iterator operator++() { 478 return iterator( ++std::get<0>(it), ++std::get<1>(it) ); 479 } 480 bool operator!=( const iterator &other ) const { return it != other.it; } 481 value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it) ); } 482 }; 483 484 iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin() ); } 485 iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end() ); } 486 }; 487 488 template< typename T1, typename T2, typename T3 > 489 struct group_iterate_t<T1, T2, T3> { 490 private: 491 std::tuple<T1, T2, T3> args; 492 public: 493 group_iterate_t( const T1 & v1, const T2 & v2, const T3 & v3 ) : args(v1, v2, v3) {}; 494 495 template<size_t I> using Iter = decltype(std::get<I>(args).begin()); 496 using value_type = std::tuple<decltype(*std::get<0>(args).begin()), decltype(*std::get<1>(args).begin()), decltype(*std::get<2>(args).begin())>; 497 498 struct iterator { 499 typedef std::tuple<Iter<0>, Iter<1>, Iter<2>> IterTuple; 500 IterTuple it; 501 iterator( Iter<0> i0, Iter<1> i1, Iter<2> i2 ) : it( i0, i1, i2 ) {} 502 iterator operator++() { 503 return iterator( ++std::get<0>(it), ++std::get<1>(it), ++std::get<2>(it) ); 504 } 505 bool operator!=( const iterator &other ) const { return it != other.it; } 506 value_type operator*() const { return std::tie( *std::get<0>(it), *std::get<1>(it), *std::get<2>(it) ); } 507 }; 508 509 iterator begin() { return iterator( std::get<0>(args).begin(), std::get<1>(args).begin(), std::get<2>(args).begin() ); } 510 iterator end() { return iterator( std::get<0>(args).end(), std::get<1>(args).end(), std::get<2>(args).end() ); } 511 }; 512 513 // Helpers for the bounds checks: 492 group_iterate_t( const Args &... args ) : iterables( args... ) {} 493 494 using iterator = base_iterator<decltype( 495 std::make_integer_sequence<std::size_t, sizeof...(Args)>())>; 496 497 iterator begin() { return iterator::make_begin( iterables ); } 498 iterator end() { return iterator::make_end( iterables ); } 499 }; 500 501 // Helpers for the bounds checks (the non-varatic part of group_iterate): 514 502 static inline void runGroupBoundsCheck(size_t size0, size_t size1) { 515 503 assertf( size0 == size1, … … 524 512 } 525 513 526 /// performs bounds check to ensure that all arguments are of the same length.514 /// Performs bounds check to ensure that all arguments are of the same length. 527 515 template< typename... Args > 528 516 group_iterate_t<Args...> group_iterate( Args &&... args ) { … … 531 519 } 532 520 533 /// does not perform a bounds check - requires user to ensure that iteration terminates when appropriate.521 /// Does not perform a bounds check - requires user to ensure that iteration terminates when appropriate. 534 522 template< typename... Args > 535 523 group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
Note: See TracChangeset
for help on using the changeset viewer.