Iurii Sorokin
Iurii Sorokin

Reputation: 115

Iterate over vector of vectors with one iterator

Suppose I have a

std::vector< std::vector< int > > vvi;

I want to hide the fact that vvi is a vector of vectors, and create an iterator over all its contained int elements, like:

class vvi_iterator; // Iterator over std::vector< std::vector< int > >
                    // I am looking for a template of such class, 
                    // or I would need to implement it on my own.

vvi_iterator itBegin = make_vvi_iterator_begin( vvi );  // helper function
                                // that creates a vvi_iterator pointing to the 
                                // first element of the first vector

vvi_iterator itEnd   = make_vvi_iterator_end( vvi ); // helper function
                                // that creates a vvi_iterator in the "end" state
                                // (e.g. pointing behind the last element of the 
                                // last vector)


// This is how I'm going to use it:

auto itRange = boost::iterator_range<vvi_iterator>( itBegin, itEnd );

for( int& i : itRange ) {
   doSomething(i);
}

I don't need to insert/erase int elements.

I can use boost, as well as other external libraries.

I can use C++11, but not c++14. Yet, solutions involving c++14 would also be interesting.

Thanks in advance.

.

.

UPD.: Folded loops don't work for me. In my real use case I have

class A {
private:
    std::array< std::unordered_map< std::unique_ptr< SomeDataClass > > > _own_data;
}

class B {
private:
    std::vector< std::reference_wrapper< SomeDataClass > > _referenced_data;
}

and I need to pass references to all SomeDataClass objects from A, as well as from B, to some other class X. I don't want class X to know about the internal structure of A and B, and I don't want to treat them separately.

If I did not have folded containers, I could have used boost::indirect_iterator:

class A {
private:
    std::array< std::unique_ptr< SomeDataClass > > _own_data;

public:
    boost::iterator_range< 
        boost::indirect_iterator<
            std::array< std::unique_ptr< SomeDataClass> >::iterator > >
    getSomeData() {
        return { boost::make_indirect_iterator( _own_data.begin() ),
                 boost::make_indirect_iterator( _own_data.end()   ) }
    }
}

class X {
private:
    doSomething( SomeDataClass& someData );

public:
    template<typename IteratorRangeType>
    processSomeData( IteratorRangeType itRange ) {
        for( auto& someData : itRange ) {
            doSomething( someData ); 
        }
    }
}



int main(int, char**) {
    A a;
    X x;
    x.processsSomeData( a.getSomeData() ); // isn't it beautiful? 
}

Now, I hope there exists something like folded_container_iterator, and I hope I can combine it with the boost::indirect_iterator and boost_iterator_range

Upvotes: 3

Views: 615

Answers (1)

Jarod42
Jarod42

Reputation: 218238

With range-v3, you may do

std::vector< std::vector< int > > v /* = ...*/;

for (auto e : v | ranges::view::join) {
    std::cout << e << std::endl;
}

Demo

Upvotes: 2

Related Questions