2

During the running of a modern C++ range-based for loop on a std::vector or c arrays. My initial guess would be no unless you use pointers and pointer math but just wanted to check. What I want to do is to check the adjacent elements to examine how because they might effect my current code. I also know that there is more that on item in the vector. The code would like something like:

std::vector<Item> v;
// do work
for(auto& item : v)
{
    //do more work
    auto pos = //some way to find get the position
    if(/*pos is the first position*/)
    {
          process(item, pos+1);
    }
    else if(/*pos is the last position*/)
    {
          process(item, pos-1);
    }
    else
    {
          process(item, pos-1, pos+1);
    }
}

I do not care about iterator if the object is a first object last object or middle object.

  • Can you maybe elaborate a bit on what you're trying to do with the position after you obtain it? `operator-` is well defined and constant time for random access containers like vector. – Mark B Jan 23 '15 at 18:38
  • See http://stackoverflow.com/questions/10962290/find-position-of-element-in-c11-range-based-for-loop – sfjac Jan 23 '15 at 18:52
  • This is a special case (continuous memory) of the duplicate (which has no accepted answer). The answers provided there are plain overkill. –  Jan 23 '15 at 19:36

2 Answers2

2

One way to do this is to search for the element using std::find. Then if you found the element, you can use std::distance to calculate the index.

std::vector<int> myVec;
int valToFind = 5;

auto it = std::find(myVec.begin(), myVec.end(), valToFind);
if (it != myVec.end())
{
    int index = std::distance(myVec.begin(), it);
}

Note that since std::vector is contiguous, you could also get the same value from pointer arithmetic

if (it != myVec.end())
{
    int index = it - myVec.begin()
}

Both methods of finding the index (after std::find) are O(1) since vectors are random access containers.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • this would only assume all element are unique and I do not think it would work for range-based for loop –  Jan 23 '15 at 19:13
2

For sequences with continuous memory:

for(const auto& element : sequence) {
    // If the sequence has a member data()
    // std::array, std::vector or std::string 
    auto index = &element - sequence.data();

    // If the sequence is an array
    auto index = &element - sequence;

    // If the sequence supports operator []
    // All of above
    auto index = &element - &sequence[0];

    // Generally
    auto index = &element - &*std::begin(sequence);
}
Casey
  • 41,449
  • 7
  • 95
  • 125
  • 1
    I guess you could do just `&sequence[0]` and have that work for vector, string, std::array, and plain array. – Barry Jan 23 '15 at 19:00