C++11: Range-looping vector from the second element?

前端 未结 2 418
天命终不由人
天命终不由人 2020-12-19 04:27

I have a std::vector v; (initialized). How can I use the range-for loop for accessing all elements except the first one (on index zero). For

2条回答
  •  自闭症患者
    2020-12-19 04:54

    Create a wrapper for which begin() and end() return the correct iterators and then you can use that as the second argument.

    #include 
    #include 
    
    template< typename Collection >
    class FromNth
    {
        Collection& coll_;
        size_t offset_;
    
    public:
        FromNth( Collection& coll, size_t offset )
            : coll_( coll ), offset_( offset )
        {
        }
    
        // will nicely resolve to const_iterator if necessary
        auto begin() const -> decltype( coll_.begin() ) 
           { return coll_.begin() + offset_; }
    
        auto end() const -> decltype( coll_.end() )
           { return coll_.end(); }
    };
    
    template< typename Collection >
    FromNth makeFromNth( Collection& collection, size_t offset )
    {
         return FromNth( collection, offset );
    }
    
    template< typename Collection >
    auto begin( const FromNth & wrapper ) -> decltype( wrapper.begin() )
    {   
       return wrapper.begin();
    }
    
    template< typename Collection >
    auto end( const FromNth & wrapper ) -> decltype( wrapper.end() )
    {  
       return wrapper.end();
    }
    
    int main()
    {
       std::vector< int > coll { 2, 3, 5, 7, 11, 13, 17, 19, 23 };
    
       for( auto x : makeFromNth( coll, 1 ) )
       {
           std::cout << x << '\n';
       }
       return 0;
    }
    

    Note that my fromNth "begin" is undefined behaviour if the size of the input is less than the offset. (If it's equal then it's well defined and begin == end). Therefore do a size check first.

    Note: if you are using a recent enough version of boost then iterator_range may already provide you such a "collection" that is similar to my "FromNth".

    for( auto const& s : boost::make_iterator_range( v.begin() + 1, v.end() ) )
    {
        process( s );
    }
    

    Note: the code above worked on CodingGround using C++11 GNU 4.8.3. (That site is very slow though). From C++14 you will not need the ->decltype statements (which are needed in C++11 for templates).

    Output:

    sh-4.3$ g++ -std=c++11 -o main *.cpp
    sh-4.3$ main
    3
    5
    7
    11
    13
    17
    19
    23 
    

提交回复
热议问题