Note that there are some explanatory texts on larger screens.

plurals
  1. PODeriving from std::back_insert_iterator?
    primarykey
    data
    text
    <p>I want to derive from <code>std::back_insert_iterator</code> to create a kind of filter for a string type, say <code>back_xml_insert_iterator</code>, that will examine the characters passed through it looking for characters that can not be emitted "naked" into an XML stream, e.g., <code>'"'</code>, <code>'&amp;'</code>, <code>'&lt;'</code>, <code>'&gt;'</code>, and <code>'\''</code>, and will on-the-fly insert their character entity references instead, e.g., <code>"&amp;#34;"</code> for <code>'"'</code>.</p> <pre><code>template&lt;class StringType&gt; class back_xml_insert_iterator : public std::back_insert_iterator&lt;StringType&gt; { typedef std::back_insert_iterator&lt;StringType&gt; base_type; public: typedef typename base_type::container_type container_type; typedef typename StringType::value_type value_type; explicit back_xml_insert_iterator( StringType &amp;s ) : base_type( s ) { } back_xml_insert_iterator&amp; operator=( value_type c ) { switch ( c ) { case '"': case '&amp;': case '\'': case '&lt;': case '&gt;': char buf[10]; this-&gt;container-&gt;append( "&amp;#" ); this-&gt;container-&gt;append( itoa( c, buf ) ); this-&gt;container-&gt;push_back( ';' ); break; default: this-&gt;container-&gt;push_back( c ); } return *this; } }; </code></pre> <p>This compiles fine. When I create an instance, I confirmed that the constructor is called, but my <code>operator=()</code> is never called. I think it's because the inherited <code>operator*()</code> returns a <code>back_insert_iterator&amp;</code> and not a <code>back_xml_insert_iterator&amp;</code> so <code>back_insert_iterator::operator=()</code> is called rather than mine (since <code>operator=()</code> is not, nor can not be, <code>virtual</code>).</p> <p>If that's the case, then it seems impossible to derive from <code>back_insert_iterator</code> in a useful way.</p> <p>If I instead create my own <code>back_insert_iterator_base</code> class like:</p> <pre><code>template&lt;class ContainerType,class DerivedType&gt; class back_insert_iterator_base : public std::iterator&lt;std::output_iterator_tag,void,void,void,void&gt; { public: typedef ContainerType container_type; DerivedType&amp; operator*() { return *static_cast&lt;DerivedType*&gt;( this ); } DerivedType&amp; operator++() { return *static_cast&lt;DerivedType*&gt;( this ); } DerivedType&amp; operator++(int) { return *static_cast&lt;DerivedType*&gt;( this ); } protected: back_insert_iterator_base( ContainerType &amp;c ) : container( &amp;c ) { } ContainerType *container; }; </code></pre> <p>and derive from that instead like:</p> <pre><code>template&lt;class StringType&gt; class back_xml_insert_iterator : public back_insert_iterator_base&lt; StringType, back_xml_insert_iterator&lt;StringType&gt; &gt; { // ... as before ... }; </code></pre> <p>then <code>back_xml_insert_iterator</code> works as desired. So is it possible to derive from <code>std::back_insert_iterator</code> and have it work as desired?</p> <h1>Update</h1> <p>Here's how I'd like to use the <code>back_xml_insert_iterator</code>. First, there would be the helper function:</p> <pre><code>template&lt;class StringType&gt; inline back_xml_insert_iterator&lt;StringType&gt; back_xml_inserter( StringType &amp;s ) { return back_xml_insert_iterator&lt;StringType&gt;( s ); } </code></pre> <p>Then writing a <code>to_xml()</code> function would be trivial:</p> <pre><code>template&lt;class InputStringType,class OutputStringType&gt; inline void to_xml( InputStringType const &amp;in, OutputStringType *out ) { std::copy( in.begin(), in.end(), back_xml_inserter( *out ) ); } </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload