0

Can I convert std::vector element pointer to index with this?

http://coliru.stacked-crooked.com/a/cedf3d849539e001

template<class T>
std::size_t get_index(std::vector<T>& vec, T* ptr){
    const std::size_t i = ptr - &(*vec.begin());
    return i;
}

If elements in vector is guaranteed to be contiguous, then I think we can do such pointer arithmetic... Or no?

tower120
  • 5,007
  • 6
  • 40
  • 88
  • 3
    why do you want to do this? Use iterators intstead of pointers and use `std::distance` instead of pointer arithmetics – 463035818_is_not_an_ai Oct 26 '17 at 11:38
  • I want to use it with https://github.com/tower120/trackable_ptr, like std::vector> – tower120 Oct 26 '17 at 11:40
  • 1
    Yes you can (as long as `ptr` really point on element of vector).... BTW `ptr - vec.data()` seems more appropriate. – Jarod42 Oct 26 '17 at 11:40
  • `std::distance` is bad in this case - it is supposed to be used when iterators might or might not provide random access. If you are working with random access iterators it is better to just subtract one from another. Keep your code explicit. –  Oct 26 '17 at 11:41
  • 1
    Note that changes to the vector can make your pointer invalid. – stark Oct 26 '17 at 11:44
  • @stark see https://github.com/tower120/trackable_ptr, to leave them valid. – tower120 Oct 26 '17 at 11:44
  • @Ivan if `std::distance` is used with random access iterators it will just subtract one from the other. According to your reasoning one shouldnt use `std::vector` but c-arrays just to have more explicit pointers in the code. – 463035818_is_not_an_ai Oct 26 '17 at 11:44
  • @tobi303 Yes, it exists for another reason. It should be used in algorithms that can be used with both random access iterators and non-random access iterators. If you are using it with something that is guaranteed to be a random access iterator, then there are no reasons to overcomplicate your code. Seeing `std::distance` call can confuse programmer and might make him recheck surrounding code. –  Oct 26 '17 at 11:47
  • 1
    @Ivan well, its a matter of taste. I get your point and my original comment was just meant to make sure that OP is aware that desired functionality is already available – 463035818_is_not_an_ai Oct 26 '17 at 11:51

2 Answers2

2

Vector elements are stored contiguously, yes. You can also use std::vector<T>::data() instead of &*std::vector<T>::begin().

You can read more at: http://en.cppreference.com/w/cpp/container/vector

PS: There is already a question about this - Are std::vector elements guaranteed to be contiguous?

2

If elements in vector is guaranteed to be contiguous, then I think we can do such pointer arithmetic...

Elements in vector are guaranteed to be contiguous, and you can use such pointer arithmetic indeed.

However, there is a caveat: addressof operator can be overloaded to return something other than the address. If you cannot guarantee that it won't be overloaded, use std::addressof instead.

Or simply use std::vector::data as shown by Ivan.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • > However, there is a caveat: addressof operator can be overloaded to return something other than the address... - what?? – tower120 Oct 26 '17 at 11:43
  • @tower120 operators whose operands are user defined types can be overloaded in c++. You can make those overloads do anything silly. Example: https://msdn.microsoft.com/en-us/library/31k6d0k7.aspx?f=255&MSPPError=-2147217396 – eerorika Oct 26 '17 at 11:46