Converting iterator to pointers, revisited

S

Simon Elliott

I have some code where it's necessary to convert an iterator to a
pointer, to pass the pointer to a legacy function. I've been looking at
ways of encapsulating this, so I put together a short test app:

#include <vector>
#include <iostream>

int main (int argc, char *argv[])
{
std::vector<int> vi;
vi.push_back(1);
vi.push_back(2);
vi.push_back(3);
std::vector<int>::iterator ii = vi.begin();
int* pi = &*ii;
std::cout << "result:" << *pi << std::endl;
return(0);
}

I want to document and encapsulate the iterator to pointer conversion,
along these lines:

pi = iterator_to_pointer(ii);

*** Attempt#1

#define iterator_to_pointer(i) &*i

This works but it's an Evil Macro. (It should probably be parenthesised
a bit better but I don't want to go down this route so I haven't
bothered.)


*** Attempt#2

int* iterator_to_pointer(std::vector<int>::iterator i)
{
return(&*(i));
}

This works but it's insufficiently generic to be useful. The obvious
way forward is to make this a template:


*** Attempt#3

template<class T> typename T::value_type* iterator_to_pointer(typename
T::iterator i)
{
return(&*(i));
}

This template isn't matched by my line
pi = iterator_to_pointer(ii);

In g++: error: no matching function for call to
`iterator_to_pointer(__gnu_cxx::__normal_iterator<int*,
std::vector<int, std::allocator<int> > >&)'

I can't work out why this isn't matched. Any ideas?

BTW, I expect iterator_to_pointer() not to work with oddities such as
std::vector<bool> but it would be a nice bonus if it wouldn't compile
if someone tries to use it with std::vector<bool>.
 
?

=?iso-8859-2?Q?Ale=b9=20Pergl?=

I have some code where it's necessary to convert an iterator to a
pointer, to pass the pointer to a legacy function.
...
std::vector<int>::iterator ii = vi.begin();
int* pi = &*ii;

This is not a conversion of any sort. You are merely obtaining a reference
to the item in the vector that the iterator is positioned at and then getting
the address of that item and assigning it to pi. That's quite a normal way
of doing this kind of thing so I wouldn't bother with creating a specific
function for it.
*** Attempt#3

template<class T> typename T::value_type* iterator_to_pointer(typename
T::iterator i)
{
return(&*(i));
}
...
In g++: error: no matching function for call to
`iterator_to_pointer(__gnu_cxx::__normal_iterator<int*,
std::vector<int, std::allocator<int> > >&)'

The compiler is unable to deduce the template parameter T from what you are
providing as an argument to the function. You are providing vector<int>::iterator
but the compiler cannot figure out that you want T to be vector<int>. If
you really want to create a function like this (discouraged), do it like
this:

template<class T> typename T::pointer iterator_to_pointer(T& i)
{
return(&*(i));
}
 
F

fluidparody

This one seems to work:

#include <iostream>
#include <vector>

template <typename T, typename I>
T* iterator_to_pointer(I i)
{
return (&(*i));
}

int main()
{
std::vector<int> vi;
vi.push_back(1);
vi.push_back(2);
vi.push_back(3);
std::vector<int>::iterator ii = vi.begin();

int *pi = iterator_to_pointer<int, std::vector<int>::iterator >
(ii);

std::cout << *pi << std::endl;

return 0;
}
 
S

Simon Elliott

This is not a conversion of any sort. You are merely obtaining a
reference to the item in the vector that the iterator is positioned
at and then getting the address of that item and assigning it to pi.
That's quite a normal way of doing this kind of thing so I wouldn't
bother with creating a specific function for it.

Fair enough. I want to reduce the maintenace burden, but if it's fairly
commonplace and well understood, perhaps I won't bother.
The compiler is unable to deduce the template parameter T from what
you are providing as an argument to the function. You are providing
vector<int>::iterator but the compiler cannot figure out that you
want T to be vector<int>. If you really want to create a function
like this (discouraged), do it like this:

template<class T> typename T::pointer iterator_to_pointer(T& i)
{
return(&*(i));
}

The iterator::pointer type seems to be patchily documented (eg it's not
in the docs for my compiler, BCB6). Is it a fairly new/non standard
feature?
 
?

=?iso-8859-1?q?Stephan_Br=F6nnimann?=

Simon said:
The iterator::pointer type seems to be patchily documented (eg it's not
in the docs for my compiler, BCB6). Is it a fairly new/non standard
feature?

IIRC from Bjarne Stroustrup iterators are implementation specific
(thus the surprising error message in the original post):
you only can rely on their semantics.

Regards, Stephan
(e-mail address removed)
Open source rating and billing engine for communication networks.
 
B

Bo Persson

Simon Elliott said:
The iterator::pointer type seems to be patchily documented (eg it's
not
in the docs for my compiler, BCB6). Is it a fairly new/non standard
feature?

The formally correct way to access the pointer type is

typename std::iterator_traits<T>::pointer

which might be equivalent to T::pointer, but doesn't have to be.


Bo Persson
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,997
Messages
2,570,241
Members
46,831
Latest member
RusselWill

Latest Threads

Top