Why doesn't my custom iterator work with the STL copy?

前端 未结 4 1646
既然无缘
既然无缘 2021-01-02 05:02

I wrote an OutputIterator for an answer to another question. Here it is:

#include 

using namespace std;

template< typename T, typename U &g         


        
相关标签:
4条回答
  • 2021-01-02 05:27
    #include <queue>
    #include <algorithm>
    #include <iterator>
    #include <iostream>
    
    using namespace std;
    
    template< typename T, typename U >
    class queue_inserter
    {
        queue<T, U> &qu;
    
    public:
        // for iterator_traits to refer
        typedef output_iterator_tag iterator_category;
        typedef T value_type;
        typedef ptrdiff_t difference_type;
        typedef T* pointer;
        typedef T& reference;
    
        queue_inserter(queue<T,U> &q) : qu(q) { }
        queue_inserter<T,U>& operator ++ () { return *this; }
        queue_inserter<T,U> operator * () { return *this; }
        void operator = (const T &val) { qu.push(val); }
    };
    
    template< typename T, typename U >
    queue_inserter<T,U> make_queue_inserter(queue<T,U> &q)
    {
        return queue_inserter<T,U>(q);
    }
    
    int main()
    {
        // uses initalizer list (C++0x), pass -std=c++0x to g++
        vector<int> v({1, 2, 3});
        queue<int, deque<int>> q;
        copy(v.cbegin(), v.cend(), make_queue_inserter(q));
        while (!q.empty())
        {
            cout << q.front() << endl;
            q.pop();
        }
    }
    

    This should do it with iterator_traits; a helper struct in <iterator> which defines all types an iterator should typically define. Functions in <algorithm>, refer to these types when required like iterator_traits<it>::iterator_category or say iterator_traits<it>::value_type, etc. Just defining them inside one's custom iterator would do the trick. This is the modern way of writing iterators, as opposed to the classical way of inheriting from std::iterator. Having a look at <iterator> reveals that even std::iterator defines these types i.e. iterator_category, difference_type, etc. This is the reason, when inherited from std::iterator, the derived iterator class gets these due to heredity.

    0 讨论(0)
  • 2021-01-02 05:31

    Your iterator doesn't meet the requirement for an 'assignable' type which is a requirement for an output iterator because it contains a reference and assignable types need to ensure that after t = u that t is equivalent to u.

    You can provide a suitable specialization for iterator_traits for your iterator either by deriving from a specialization of std::iterator or by providing one explicitly.

    namespace std
    {
        template<> struct iterator_traits<MyIterator>
        {
            typedef std::output_iterator_tag iterator_category;
            typedef void value_type;
            typedef void difference_type;
        };
    }
    
    0 讨论(0)
  • 2021-01-02 05:46

    Derive it from std::iterator. If you are interested the Dr. Dobb's has an article about custom containers and iterators.

    0 讨论(0)
  • 2021-01-02 05:49

    Your queue_inserter needs to be derived from std::iterator so that all the typedefs such as value_type are properly defined since these are used inside STL algorithms This definition works:

    template< typename T, typename U >
    class queue_inserter : public std::iterator<std::output_iterator_tag, T>{
        queue<T, U> &qu;  
    public:
        queue_inserter(queue<T,U> &q) : qu(q) { }
        queue_inserter<T,U> operator ++ (int) { return *this; }
        queue_inserter<T,U> operator ++ () { return *this; }
        queue_inserter<T,U> operator * () { return *this; }
        void operator = (const T &val) { qu.push(val); }
    };
    
    0 讨论(0)
提交回复
热议问题