I wrote an OutputIterator for an answer to another question. Here it is:
#include
using namespace std;
template< typename T, typename U &g
#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.
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;
};
}
Derive it from std::iterator. If you are interested the Dr. Dobb's has an article about custom containers and iterators.
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); }
};