7

I understand (at least I think I do) that pointers can be used as random STL iterators.

Why does the following code not compile unless I cast the pointer to an iterator?

vector<int> v{1, 2, 3};
v.erase(&v[0]);
gman
  • 100,619
  • 31
  • 269
  • 393
jackhab
  • 17,128
  • 37
  • 99
  • 136

3 Answers3

12

You can pass pointers to algorithms like std::sort, std::find, or std::copy. These are templates that are configurable for anything that works as an appropriate iterator.

This does not mean that different iterators necessarily convert to each other.

The method erase of the std::vector<int> container can only work with iterators to elements of the same vector. As has been pointed out this may be implemented as a pointer, but it usually is not, for reasons stated here: C++ std::vector<>::iterator is not a pointer, why?

Consider std::find:

template< class InputIt, class T >
InputIt find( InputIt first, InputIt last, const T& value );

Here InputIt is a template parameter. The template std::find will work with any iterator type that fulfills the requirements of an input iterator, and whose operator* returns something that can be compared to type T. Pointers work well here. As Fire Lancer pointed out correctly in a comment, both first and last must be of type InputIt.

Now compare this to std::vector::erase:

iterator erase( const_iterator pos );

This takes a const_iterator, which is one of the typedefs of the std::vector class. This is one particular type of iterator, not a template parameter.

PaulR
  • 3,587
  • 14
  • 24
  • 1
    Well passing **pairs** of pointers to those algorithms is effectively a random access iterator type. But, you still cant pass a pointer and a vector iterator as a "pair" to those, even if the pointer is inside the vector. – Fire Lancer Sep 11 '17 at 12:08
1

The definition of vector.erase(...) is

iterator erase( const_iterator pos );

The const iterator is a class in itself. So if there was a conversion of a plain pointer to this class, then this could be done. But I don't think there is any.

But one thing is to use it in a place where an iterator is expected, and another is to use in algorithms.

Where an iterator is required, only a iterator can be used.

In algorithms, an iterator is not expected. Only a object for which a Concept of an iterator is satisified (usually a begin and end return the required iterator/pointer).

Robert Andrzejuk
  • 5,076
  • 2
  • 22
  • 31
  • Algorithms expect iterators, not "objects for which a begin/end..." whatever. – juanchopanza Sep 11 '17 at 12:11
  • 1
    Algorithms use templates - the parameters are not concrete types of ```iterator```. You can pass any object which satisfies the Concept of an ```iterator``` into the functions. – Robert Andrzejuk Sep 11 '17 at 13:04
0

Although pointers are iterators, they are not the same type as vector iterators (at least they do not have to be).

You can convert a pointer to an element of a vector into an itertor using iterator and pointer arithmetic like this.

std::vector<int> v{1, 2, 3};

int* p = &v[0]; // a pointer

auto v_iter = v.begin() + std::distance(v.data(), p); // an equivalent vector::iterator

v.erase(v_iter);

This only works with contiguous containers like std::vector or std::array.

Galik
  • 47,303
  • 4
  • 80
  • 117