|  | Home | Libraries | People | FAQ | More | 
The C++ Standard library lacks an important feature, namely the support for any formatted output of containers. Sure, it's fairly easy to write a custom routine to output a specific container, but doing so over and over again is tedious at best. In this section we will demonstrate some more of the capabilities of Spirit.Karma for generating output from arbitrary STL containers. We will build on the example presented in an earlier section (see Warming Up).
The full source code of the example shown in this section can be found here: num_list2.cpp.
          This time we take advantage of Karma's List
          (%) operator. The semantics
          of the list operator are fully equivalent to the semantics of the sequence
          we used before. The generator expression
        
double_ << *(',' << double_)
is semantically equivalent to the generator expression
double_ % ','
          simplifying the overall code. The list operator's attribute is compatible
          with any STL container as well. For a change we use a std::vector<double> instead of the std::list<double> we used before. Additionally, the routine
          generate_numbers takes
          the container as a template parameter, so it will now work with any STL
          container holding double numbers.
        
template <typename OutputIterator, typename Container> bool generate_numbers(OutputIterator& sink, Container const& v) { using boost::spirit::karma::double_; using boost::spirit::karma::generate_delimited; using boost::spirit::ascii::space; bool r = generate_delimited( sink, // destination: output iterator double_ % ',', // the generator space, // the delimiter-generator v // the data to output ); return r; }
| ![[Note]](../../../images/note.png) | Note | 
|---|---|
| 
            Despite the container being a template parameter, the Spirit.Karma
            formatting expression ( | 
          The output routine developed above is still not generically usable for
          all types of STL containers and for arbitrary elements stored in them.
          In order to be usable the items stored in the container still need to be
          convertible to a double. Fortunately
          Spirit.Karma is capable to output arbitrary data types
          while using the same format description expression. It implements the
          stream
          generators which are able to consume any attribute type as long as a matching
          standard streaming operator is defined. I.e. for any attribute type Attrib a function:
        
std::ostream& operator<< (std::ostream&, Attrib const&);
          needs to be available. The stream generator will use the
          standard streaming operator to generate the output.
        
          The following example modifies the code shown above to utilize the stream
          operator, which makes it compatible with almost any data type. We implement
          a custom data type complex
          to demonstrate this. The example shows how it is possible to integrate
          this (or any other) custom data type into the Spirit.Karma
          generator framework.
        
This is the custom data structure together with the required standard streaming operator:
// a simple complex number representation z = a + bi struct complex { complex (double a, double b = 0.0) : a(a), b(b) {} double a; double b; }; // the streaming operator for the type complex std::ostream& operator<< (std::ostream& os, complex const& z) { os << "{" << z.a << "," << z.b << "}"; return os; }
          And this is the actual call to generate the output from a vector of those.
          This time we interleave the generated output with newline breaks (see
          eol),
          putting each complex number onto a separate line:
        
template <typename OutputIterator, typename Container> bool generate_numbers(OutputIterator& sink, Container const& v) { using boost::spirit::karma::stream; using boost::spirit::karma::generate; using boost::spirit::karma::eol; bool r = generate( sink, // destination: output iterator stream % eol, // the generator v // the data to output ); return r; }
The code shown is fully generic and can be used with any STL container as long as the data items stored in that container implement the standard streaming operator.
The full source code of the example presented in this section can be found here: num_list3.cpp.