Converting iterator to pointers, revisited

Discussion in 'C++' started by Simon Elliott, Jan 12, 2006.

  1. 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>.

    --
    Simon Elliott http://www.ctsn.co.uk
     
    Simon Elliott, Jan 12, 2006
    #1
    1. Advertising

  2. > 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));
    }
     
    =?iso-8859-2?Q?Ale=b9=20Pergl?=, Jan 12, 2006
    #2
    1. Advertising

  3. Simon Elliott

    Guest

    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;
    }
     
    , Jan 12, 2006
    #3
  4. On 12/01/2006, AleĀ¹ Pergl wrote:

    > > 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.


    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?

    --
    Simon Elliott http://www.ctsn.co.uk
     
    Simon Elliott, Jan 13, 2006
    #4
  5. Simon Elliott wrote:

    >
    > 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?
    >
    > --
    > Simon Elliott http://www.ctsn.co.uk


    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

    Open source rating and billing engine for communication networks.
     
    =?iso-8859-1?q?Stephan_Br=F6nnimann?=, Jan 13, 2006
    #5
  6. Simon Elliott

    Bo Persson Guest

    "Simon Elliott" <Simon at ctsn.co.uk> skrev i meddelandet
    news:43c7d601$0$87299$...
    >>
    >> 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?


    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
     
    Bo Persson, Jan 14, 2006
    #6
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Hendrik Maryns
    Replies:
    18
    Views:
    1,446
  2. greg
    Replies:
    6
    Views:
    468
    Dietmar Kuehl
    Jul 17, 2003
  3. Replies:
    6
    Views:
    662
    Jim Langston
    Oct 30, 2005
  4. Sheldon

    function arguments and pointers revisited

    Sheldon, Nov 7, 2007, in forum: C Programming
    Replies:
    4
    Views:
    309
    Sheldon
    Nov 7, 2007
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    694
Loading...

Share This Page