我想从std::back_insert_iterator
派生出来,为字符串类型创建一种过滤器,例如back_xml_insert_iterator
,它将检查通过它的字符,以查找无法“裸露”到XML流中的字符,例如'"'
,'&'
, '<'
,'>'
和'\''
,并将即时插入其字符实体引用,例如"""
的'"'
。
template<class StringType>
class back_xml_insert_iterator : public std::back_insert_iterator<StringType> {
typedef std::back_insert_iterator<StringType> base_type;
public:
typedef typename base_type::container_type container_type;
typedef typename StringType::value_type value_type;
explicit back_xml_insert_iterator( StringType &s ) : base_type( s ) { }
back_xml_insert_iterator& operator=( value_type c ) {
switch ( c ) {
case '"':
case '&':
case '\'':
case '<':
case '>':
char buf[10];
this->container->append( "&#" );
this->container->append( itoa( c, buf ) );
this->container->push_back( ';' );
break;
default:
this->container->push_back( c );
}
return *this;
}
};
这样编译就可以了。创建实例时,我确认已调用构造函数,但从未调用过
operator=()
。我认为这是因为继承的operator*()
返回的是back_insert_iterator&
而不是back_xml_insert_iterator&
,所以back_insert_iterator::operator=()
被称为而不是我的(因为operator=()
不是,也不能是virtual
)。如果真是这样,那么似乎不可能以有用的方式从
back_insert_iterator
派生。如果我改为创建自己的
back_insert_iterator_base
类,例如:template<class ContainerType,class DerivedType>
class back_insert_iterator_base :
public std::iterator<std::output_iterator_tag,void,void,void,void> {
public:
typedef ContainerType container_type;
DerivedType& operator*() {
return *static_cast<DerivedType*>( this );
}
DerivedType& operator++() {
return *static_cast<DerivedType*>( this );
}
DerivedType& operator++(int) {
return *static_cast<DerivedType*>( this );
}
protected:
back_insert_iterator_base( ContainerType &c ) : container( &c ) {
}
ContainerType *container;
};
并从中得出类似:
template<class StringType>
class back_xml_insert_iterator :
public back_insert_iterator_base< StringType, back_xml_insert_iterator<StringType> > {
// ... as before ...
};
然后
back_xml_insert_iterator
会按需工作。那么有可能从std::back_insert_iterator
派生出来并使其按需工作吗?更新资料
这是我想使用
back_xml_insert_iterator
的方式。首先,将有辅助函数:template<class StringType> inline
back_xml_insert_iterator<StringType> back_xml_inserter( StringType &s ) {
return back_xml_insert_iterator<StringType>( s );
}
然后编写
to_xml()
函数将很简单:template<class InputStringType,class OutputStringType> inline
void to_xml( InputStringType const &in, OutputStringType *out ) {
std::copy( in.begin(), in.end(), back_xml_inserter( *out ) );
}
最佳答案
您不应尝试从未考虑继承的类中继承。通常,您不应从标准容器或迭代器继承。请注意,在大多数情况下,迭代器是在模板中使用的,这些模板首先不需要类型层次结构。
通常最好是通过提供函子或实现自己的迭代器从外部添加功能-这应该并不复杂。如果您确实想实现自己的迭代器,则可以看一下boost中的迭代器适配器库。
关于c++ - 从std::back_insert_iterator派生?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3488670/