C++ turn vector iterator into index

I've got a question. I have a vector that contains tuples:

vector<tuple<int, int> > my_vector

Let's say I want to turn my for loop iterator in an index for whatever reason:

// Example program
#include <vector>
#include <tuple>

using namespace std;

int main()
{        
    vector<tuple<int, int> > my_vector;
    my_vector.push_back(make_tuple(1, 1));
    my_vector.push_back(make_tuple(2, 2));
    my_vector.push_back(make_tuple(3, 3));

    for (auto iterator : my_vector)
    {
        size_t index = distance(my_vector.begin(), iterator);
    }       
}

I honestly do not understand what I have to change to get it running. The problems seems to be my use of the iterator in distance. Maybe somebody can give me some advice.

3 answers

  • answered 2019-11-08 13:49 Evg

    The range-based for loop

    for (range_declaration : range_expression) 
        loop_statement
    

    is roughly equivalent to this code:

    for (auto begin = range_expression.begin(), end = range_expression.end(); 
         begin != end; ++begin)
    {
        range_declaration = *begin;
        loop_statement
    } 
    

    Note the * operator. So, range_declaration is not the iterator, but an element, it points to.

    If you need an index, use plain for loop:

    for (std::size_t index = 0; index < my_vector.size(); ++index)
         loop_statement
    

  • answered 2019-11-08 13:58 eerorika

    C++ turn vector iterator into index

    You can do it like this:

    std::size_t index = std::distance(std::begin(my_vector), iterator);
    

    But before you can get an index from an iterator, you first need to have an iterator. Example of an iterator to a vector:

    // iterator to i'th element
    auto iterator = std::next(my_vector.begin(), i);
    

    for (auto iterator : my_vector)
    

    Just naming a variable iterator does not make it an iterator. A range based loop goes over the elements of the container. The elements of this vector are tuples, not iterators.

    The canonical way to have an index when iterating elements of a vector is to use a traditional index loop:

    using my_vec_t = decltype(my_vector);
    for (my_vec_t::size_type i = 0; i < my_vector.size(); i++)
    

    If you really want to have the index in a range-for loop, that's possible using pointers:

    auto* front = &my_vector.front();
    for (auto& element : my_vector)
    {
        auto index = std::distance(front, &element);
    }  
    

  • answered 2019-11-08 13:58 Vlad from Moscow

    In the range based loop it is value of a container is assigned not an iterator.

    So either use the following for loop

    #include <iterator>
    
    //...
    
    for ( auto it = std::begin( my_vector); it != std::end( my_vector ); ++it )
    {
        size_t index = std::distance( std::behin( my_vector ), it );
    }
    

    Or use an ordinary for loop with an index.

    for ( std::vector<std::tuple<int, int>>::size_type i = 0; i != my_vector.size(); i++ )
    {
        auto it = std::next( std::begin( myvector ), i );
    }