我想从std::back_insert_iterator派生出来,为字符串类型创建一种过滤器,例如back_xml_insert_iterator,它将检查通过它的字符,以查找无法“裸露”到XML流中的字符,例如'"''&''<''>''\'',并将即时插入其字符实体引用,例如"&#34;"'"'

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/

10-10 04:33