我为answer to another question编写了一个OutputIterator。这是:
#include <queue>
using namespace std;
template< typename T, typename U >
class queue_inserter {
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; }
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);
}
这适用于这个小复制功能:
template<typename II, typename OI>
void mycopy(II b, II e, OI oi) {
while (b != e) { *oi++ = *b++; }
}
但它对copy
的STL algorithms
根本不起作用。以下是我得到的精彩C ++错误:
i.cpp:33: error: specialization of ‘template<class _Iterator> struct std::iterator_traits’ in different namespace
/usr/include/c++/4.0.0/bits/stl_iterator_base_types.h:127: error: from definition of ‘template<class _Iterator> struct std::iterator_traits’
/usr/include/c++/4.0.0/bits/stl_algobase.h: In function ‘_OI std::__copy_aux(_II, _II, _OI) [with _II = int*, _OI = queue_inserter<int, std::deque<int, std::allocator<int> > >]’:
/usr/include/c++/4.0.0/bits/stl_algobase.h:335: instantiated from ‘static _OI std::__copy_normal<true, false>::copy_n(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OI = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
/usr/include/c++/4.0.0/bits/stl_algobase.h:387: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OutputIterator = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
i.cpp:53: instantiated from here
/usr/include/c++/4.0.0/bits/stl_algobase.h:310: error: no type named ‘value_type’ in ‘struct std::iterator_traits<queue_inserter<int, std::deque<int, std::allocator<int> > > >’
/usr/include/c++/4.0.0/bits/stl_algobase.h:315: error: no type named ‘value_type’ in ‘struct std::iterator_traits<queue_inserter<int, std::deque<int, std::allocator<int> > > >’
/usr/include/c++/4.0.0/bits/stl_algobase.h:315: error: ‘__value’ is not a member of ‘<declaration error>’
/usr/include/c++/4.0.0/bits/stl_algobase.h:335: instantiated from ‘static _OI std::__copy_normal<true, false>::copy_n(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OI = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
/usr/include/c++/4.0.0/bits/stl_algobase.h:387: instantiated from ‘_OutputIterator std::copy(_InputIterator, _InputIterator, _OutputIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int, std::allocator<int> > >, _OutputIterator = queue_inserter<int, std::deque<int, std::allocator<int> > >]’
i.cpp:53: instantiated from here
/usr/include/c++/4.0.0/bits/stl_algobase.h:317: error: ‘__simple’ is not a valid template argument for type ‘bool’ because it is a non-constant expression
/usr/include/c++/4.0.0/bits/stl_algobase.h:317: error: ‘copy’ is not a member of ‘<declaration error>’
这是驱动程序:
int main() {
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
queue<int> q;
copy( v.begin(), v.end(), make_queue_inserter(q) );
while (q.size() > 0) {
cout << q.front() << endl;
q.pop();
}
}
为什么世界上它是专门的iterator_traits
。我的迭代器出了什么问题?我不能只编写自己的简单迭代器吗?
答案 0 :(得分:17)
您的queue_inserter
需要从std::iterator
派生,以便正确定义所有typedef,例如value_type
,因为这些在STL算法中使用,这个定义有效:
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); }
};
答案 1 :(得分:8)
从std :: iterator中导出它。如果您有兴趣,Dobb博士有一个关于自定义容器和迭代器的article。
答案 2 :(得分:6)
你的迭代器不符合'assignable'类型的要求,这是输出迭代器的一个要求,因为它包含一个引用,并且可分配的类型需要确保在t = u
后t
是u
相当于iterator_traits
。
您可以通过派生std::iterator
的特化或明确提供一个来为您的迭代器提供namespace std
{
template<> struct iterator_traits<MyIterator>
{
typedef std::output_iterator_tag iterator_category;
typedef void value_type;
typedef void difference_type;
};
}
的合适专业化。
{{1}}
答案 3 :(得分:4)
#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();
}
}
这应该与iterator_traits
一起做; <iterator>
中的辅助结构,它定义了迭代器通常应定义的所有类型。 <algorithm>
中的函数,在需要时引用这些类型,如iterator_traits<it>::iterator_category
或说iterator_traits<it>::value_type
等。只需在一个自定义迭代器中定义它们就可以了。这是编写迭代器的现代方法,而不是从std::iterator
继承的传统方式。看一下<iterator>
就会发现偶数std::iterator
定义了这些类型,即iterator_category,difference_type等。这就是从std::iterator
继承的原因,派生的迭代器类由于遗传而得到这些