Changeset 5ce0659


Ignore:
Timestamp:
Nov 9, 2022, 5:18:48 PM (2 years ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
ADT, ast-experimental, master
Children:
6a4ef0c
Parents:
271a5d3
Message:

The group_iterate_t type is now variadic, hopefully with acceptable template tricks.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/Common/utility.h

    r271a5d3 r5ce0659  
    452452
    453453// -----------------------------------------------------------------------------
    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
     458template<typename... Args>
     459class 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
    466491public:
    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):
    514502static inline void runGroupBoundsCheck(size_t size0, size_t size1) {
    515503        assertf( size0 == size1,
     
    524512}
    525513
    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.
    527515template< typename... Args >
    528516group_iterate_t<Args...> group_iterate( Args &&... args ) {
     
    531519}
    532520
    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.
    534522template< typename... Args >
    535523group_iterate_t<Args...> unsafe_group_iterate( Args &&... args ) {
Note: See TracChangeset for help on using the changeset viewer.