AkariYukari
AkariYukari

Reputation: 361

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.

Upvotes: 3

Views: 10975

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 310920

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::begin(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);
}

Upvotes: 0

eerorika
eerorika

Reputation: 238301

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);
}  

Upvotes: 4

Evg
Evg

Reputation: 26272

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

Upvotes: 2

Related Questions