Channels ▼


C++ and format_iterator

Copy-Assignment and Concept Checking

Eagle-eyed STL extenders may have spotted one remaining problem with the implementation: It is not copy-assignable. To all practical extents, this does not matter, since it's hard to conceive of any practical use case where one would need to take a copy of what is effectively a stateless output iterator. The non-copyability arises from the use of const and reference members (a practice I advocate strongly in Imperfect C++ as it makes the compiler a proactive aid in enforcing design).

Notwithstanding, the C++ standard requires copy-assignment of output iterators, and some implementations of the standard library incorporate active concept checks, preventing compilation of statements involving standard algorithms (such as the examples shown using std::copy()). So, we need to make iterator instances copyable, which is achieved by making all reference members be pointers, and by making all members mutable. Thankfully, all the necessary changes are within the format_output_iterator class template implementation (see Listing 8), and the class interface and the creator functions are unchanged.

template< typename S
          . . .
class format_output_iterator
  : . . .
  . . .
  format_output_iterator(sink_type& sink, format_type const& format)
    : m_sink(&sink)
    , m_format(::stlsoft::c_str_data(format), ::stlsoft::c_str_len(format))
    , m_n(0)
    , m_arg1(&no_arg_ref_())
    , m_arg2(&no_arg_ref_())
    , m_arg3(&no_arg_ref_())
    , m_arg4(&no_arg_ref_())
    , m_arg5(&no_arg_ref_())
    , m_arg6(&no_arg_ref_())
    , m_arg7(&no_arg_ref_())
    , m_arg8(&no_arg_ref_())
    sink_type&  sink
  , format_type const&  format
  , unsigned    n
  , A1 const&   arg1
  , A2 const&   arg2 = no_arg_ref_()
  , A3 const&   arg3 = no_arg_ref_()
  , A4 const&   arg4 = no_arg_ref_()
  , A5 const&   arg5 = no_arg_ref_()
  , A6 const&   arg6 = no_arg_ref_()
  , A7 const&   arg7 = no_arg_ref_()
  , A8 const&   arg8 = no_arg_ref_()
    : m_sink(&sink)
    , m_format(::stlsoft::c_str_data(format), ::stlsoft::c_str_len(format))
    , m_n(n)
    , m_arg1(&arg1)
    , m_arg2(&arg2)
    , m_arg3(&arg3)
    , m_arg4(&arg4)
    , m_arg5(&arg5)
    , m_arg6(&arg6)
    , m_arg7(&arg7)
    , m_arg8(&arg8)
    class_type& operator =(class_type const&);
  . . .
  template <typename A>
  void invoke_(A const& value)
      case    0:
        fmt(*m_sink, m_format, value);
      case    1:
        fmt(*m_sink, m_format, value
          , impl::ref_helper<A1>::get_ref(*m_arg1));
      case    2:
        fmt(*m_sink, m_format, value
          , impl::ref_helper<A1>::get_ref(*m_arg1) 
          , impl::ref_helper<A2>::get_ref(*m_arg2));
      case    3:
        fmt(*m_sink, m_format, value
          , impl::ref_helper<A1>::get_ref(*m_arg1) 
          , impl::ref_helper<A2>::get_ref(*m_arg2) 
          , impl::ref_helper<A3>::get_ref(*m_arg3));
        . . . 4 - 7:
  . . .
private: // Fields
  sink_type*   m_sink;
  string_type_ m_format;
  unsigned     m_n;
  A1 const*    m_arg1;
  A2 const*    m_arg2;
  A3 const*    m_arg3;
  A4 const*    m_arg4;
  A5 const*    m_arg5;
  A6 const*    m_arg6;
  A7 const*    m_arg7;
  A8 const*    m_arg8;

Listing 8


One final note: Although use of format_iterator is, like the FastFormat library as a whole, 100% type-safe, being implemented in terms of a replacement-based API means that its use is always subject to format specification defects, to which FastFormat responds by throwing an appropriate exception, as illustrated by the following code.

  headers.begin(), headers.end()
, fastformat::format_iterator(
  , "{1}{0}{2}{5}"
  , prefix
  , suffix)); // throws fastformat::missing_argument_exception

In this respect, then, it is less robust than either std::ostream_iterator and stlsoft::ostream_iterator. You should balance that against its substantially increased expressiveness and flexibility when choosing the tools for your particular requirements.

Note: if you have a good reason to ignore format specification defects, this can be done using the scoping classes -- ignore_missing_arguments_scope and ignore_unreferenced_arguments_scope -- supplied with the library.)


Many thanks to Chris Oldwood and Garth Lancaster for their efforts in helping to increase the readability of the article and to reduce its size. Any failures in either regard are entirely my own.

Related Reading

More Insights

Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.