Thread: std::iterator::pointer and std::iterator::reference

  1. #1
    Registered User
    Join Date
    Jan 2016
    Posts
    12

    std::iterator::pointer and std::iterator::reference

    Hi, I already asked this question on other forum but I didnt get any answers so I'm trying my luck here!

    I am kind of confused that when I'm using
    Code:
    std::iterator
    as base class for my
    Code:
    reverse_iterator
    I cant use type aliases that I'm inheriting from this base in my reverse_iterator
    Code:
    template<
        class Category,
        class T,
        class Distance = std::ptrdiff_t,
        class Pointer = T*,
        class Reference = T& >
    struct iterator{
    using iterator_category = Category; using value_type = T; using difference_type = Distance; using pointer = Pointer using reference = Reference; };
    I had to write return type like this
    Code:
        Reference<Iter> operator*() { tmp = current; return *(--tmp); }
        Pointer<Iter> operator->() { tmp = current; return &*--tmp; }
    because this didnt work
    Code:
    reference operator*() { tmp = current; return *(--tmp); }
    pointer operator->() { tmp = current; return &*--tmp; }
    It worked on Visual Studio but didn't work when I compiled it in cpp.sh. It have me this error
    error: 'reference' does not name a type

    Here is the code (look for commented part)

    Code:
    #include <iostream>
    #include <iterator>
    #include <vector>
    
    template<typename T>
    using Iterator_category = typename std::iterator_traits<T>::iterator_category;
    
    template<typename T>
    using Value_type = typename std::iterator_traits<T>::value_type;
    
    template<typename T>
    using Difference_type = typename std::iterator_traits<T>::difference_type;
    
    template<typename T>
    using Pointer = typename std::iterator_traits<T>::pointer;
    
    template<typename T>
    using Reference = typename std::iterator_traits<T>::reference;
    
    
    template<typename Iter>
    class reverse_iterator : public std::iterator<Iterator_category<Iter>,
                                                  Value_type<Iter>,
                                                  Difference_type<Iter>,
                                                  Pointer<Iter>,
                                                  Reference<Iter>>
    {
    public:
        using iterator_type = Iter;
    
        reverse_iterator() : current{} {}
        explicit reverse_iterator(Iter p) : current{ p } {}
    
        template<typename Iter2>
        reverse_iterator(const reverse_iterator<Iter2>& p) : current{ p.base() } {}
    
    
        Iter base() const { return current; }
    
    //  THIS WORKS
        Reference<Iter> operator*() { tmp = current; return *(--tmp); }
        Pointer<Iter> operator->() { tmp = current; return &*--tmp; }
    
    //  THIS DIDN'T WORK
    //    reference operator*() { tmp = current; return *(--tmp); }
    //    pointer operator->() { tmp = current; return &*--tmp; }  
    
    
    protected:
        Iter current;
    private:
        Iter tmp;
    };
    
    
    
    int main()
    {
        std::vector<int> vec{ 1,2,3,4,5,6,7,8,9 };
        reverse_iterator<typename std::vector<int>::iterator> iter{ vec.end() };
    
        std::cout << *iter << std::endl;
    }

    Last edited by etrusks; 02-23-2016 at 04:05 AM.

  2. #2
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    You may need to use the typename specifier

  3. #3
    Registered User
    Join Date
    Aug 2010
    Location
    Poland
    Posts
    733
    You need to specify type with the typename keyword. The reason is that your reverse_iterator is a class template and, what is really important here, its base class depends on a template argument - Iter. This means that when the compiler sees your type definition, it does not know what std::iterator<...> exactly is, because what it is depends on Iter (which is unknown). If you really want to refer to reference, pointer, and other members from std::iterator<...>, you need to qualify it:
    Code:
    typename std::iterator<VERY LONG ARGUMENT LIST>::reference METHOD();
    To avoid repeating this extremely long argument list, it would be convenient to add a typedef to the base class before:

    Code:
    template <class Iter>
    class reverse_iterator<Iter> : public std::iterator<VERY LONG ARGUMENT LIST>
    {
    private:
        typedef std::iterator<VERY LONG ARGUMENT LIST> base_type;
    
    public:
        using typename base_type::reference;
        using typename base_type::pointer;
    
    public:
        reference METHOD();
    };
    However, do you really need your own reverse iterator? Just in case you don't know, there is already a reverse iterator adaptor in STL: std::reverse_iterator<Iter>.
    Last edited by kmdv; 02-25-2016 at 02:14 PM.

  4. #4
    Registered User
    Join Date
    Jan 2016
    Posts
    12
    Hi guys, tnx for replies. Sry that I didn't answer earlier. I just did some tests myself with my own, one type alias containing, base class iterator and found out exactly what you just said and basically come to complain about it
    But your solution to this problem is just amazing. Very much appreciated! Tnx for the tip about std::reverse_iterator, but I'm just actually learning C++ so this was just an exercise

  5. #5
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    One thing that helped me sort of understand the need for typename in places was this example,
    Code:
    T * f; // assume T is our template
    How should the compiler parse that?

    Is it a pointer? Is it T times f?
    Code:
    typename T * f;
    helps the compiler understand that, hey, T is a type so that makes f a pointer to a type, T.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Iterator vs. pointer...
    By tennisstar in forum C++ Programming
    Replies: 7
    Last Post: 12-15-2012, 03:58 PM
  2. Access via iterator to pointer container
    By atlmallu in forum C++ Programming
    Replies: 2
    Last Post: 07-20-2009, 01:13 PM
  3. Passing reference from a iterator
    By garymeerschaert in forum C++ Programming
    Replies: 2
    Last Post: 06-01-2008, 05:49 AM
  4. Normal iterator pointer behavior
    By SevenThunders in forum C++ Programming
    Replies: 9
    Last Post: 04-01-2008, 12:11 PM
  5. Connecting input iterator to output iterator
    By QuestionC in forum C++ Programming
    Replies: 2
    Last Post: 04-10-2007, 02:18 AM