| Home | Libraries | People | FAQ | More

#### Auto Generator

###### Description

This module includes the description of the `auto_` generator. This generator can be used to automatically create a generator based on the supplied attribute type.

###### Header

    // forwards to <boost/spirit/home/karma/auto.hpp>
    #include <boost/spirit/include/karma_auto.hpp>

Also, see Include Structure.

###### Namespace

Name
`boost::spirit::auto_ // alias: boost::spirit::karma::auto_`

###### Model of

> `PrimitiveGenerator`

Notation

`s`

  A variable instance of any type for which a mapping to a generator type is defined (the meta function `traits::create_generator_exists` returns `mpl::true_`) or a Lazy Argument that evaluates to any type for which a mapping to a generator type is defined (the meta function `traits::create_generator_exists` returns `mpl::true_`).

###### Expression Semantics

Semantics of an expression is defined only where it differs from, or is not defined in `PrimitiveGenerator`.

Expression | Description
--- | ---
`auto_` | Create a generator instance compatible with the supplied attribute type and use it for output generation. This generator never fails (unless the underlying output stream reports an error).
`auto_(s)` | Create a generator instance compatible with the supplied literal value. This generator never fails (unless the underlying output stream reports an error).

###### Additional Requirements

The `auto_` generators can be used to emit output for any data type for which a mapping to a generator type is defined (the meta function `traits::create_generator_exists` returns `mpl::true_`). The following table outlines the predefined mapping rules from the attribute type to the generator type. These rules are applied recursively to create the generator type which can be used to generate output from the given attribute type.

Attribute type | Generator type
--- | ---
`char`, `wchar_t` | `standard::char_`, `standard_wide::char_`
`short`, `int`, `long` | `short_`, `int_`, `long_`
`unsigned short`, `unsigned int`, `unsigned long` | `ushort_`, `uint_`, `ulong_`
`float`, `double`, `long double` | `float_`, `double_`, `long_double`
`short`, `int`, `long` | `short_`, `int_`, `long_`
`long long`, `unsigned long long` | `long_long`, `ulong_long`
`bool` | `bool_`
Any string (`char const*`, `std::string`, etc.) | `string`
Any (STL) container | Kleene Star (unary `'*'`)
Any Fusion sequence | Sequence operator (`'<<'`)
`boost::optional<>` | Optional operator (unary `'-'`)
`boost::variant<>` | Alternative operator (`'|'`)

It is possible to add support for any custom data type by implementing a specialization of the customization point `traits::create_generator`. This customization can be used also to redefined any of the predefined mappings.

###### Attributes

Expression | Attribute
--- | ---
`auto_` | `hold_any`, attribute is mandatory (otherwise compilation will fail)
`auto_(s)` | `unused`

| Important
The attribute type `hold_any` exposed by some of the `auto_` generators is semantically and syntactically equivalent to the type implemented by Boost.Any. It has been added to Spirit as it has better a performance and a smaller footprint if compared to Boost.Any.

| Note
In addition to their usual attribute of type `Attrib` all listed generators accept an instance of a `boost::optional<Attrib>` as well. If the `boost::optional<>` is initialized (holds a value) the generators behave as if their attribute was an instance of `Attrib` and emit the value stored in the `boost::optional<>`. Otherwise the generators will fail.

###### Complexity

> The complexity of the `auto_` generator depends on the attribute type. Each attribute type results in a different generator type to be instantiated which defines the overall complexity.

###### Example

| Note
The test harness for the example(s) below is presented in the Basics Examples section.

Some includes:

    #include <boost/spirit/include/karma.hpp>
    #include <boost/spirit/include/support_utree.hpp>
    #include <boost/spirit/include/phoenix_core.hpp>
    #include <boost/spirit/include/phoenix_operator.hpp>
    #include <boost/fusion/include/std_pair.hpp>
    #include <iostream>
    #include <string>

Some using declarations:

    using boost::spirit::karma::auto_;

And a class definition used in the examples:

    // a simple complex number representation z = a + bi
    struct complex
    {
        complex (double a, double b)
          : a(a), b(b)
        {}

        double a;
        double b;
    };

The following construct is required to allow the `complex` data structure to be utilized as a Boost.Fusion sequence. This is required as we will emit output for this data structure with a Spirit.Karma sequence: `'{' << karma::double_ << ',' << karma::double_ << '}'`.

    BOOST_FUSION_ADAPT_STRUCT(
        complex,
        (double, a)
        (double, b)
    )

We add a specialization for the create_generator customization point defining a custom output format for the complex type. Generally, any specialization for create_generator is expected to return the proto expression to be used to generate output for the type the customization point has been specialized for.

We need to utilize `proto::deep_copy` as the expression contains literals (the `'{'`, `','`, and `'}'`) which normally get embedded in the proto expression by reference only. The deep copy converts the proto tree to hold this by value. The deep copy operation can be left out for simpler proto expressions (not containing references to temporaries). Alternatively you could use the `proto::make_expr` facility to build the required proto expression.

    namespace boost { namespace spirit { namespace traits
    {
        template <>
        struct create_generator<complex>
        {
            typedef proto::result_of::deep_copy<
                BOOST_TYPEOF('{' << karma::double_ << ',' << karma::double_ << '}')
            >::type type;

            static type call()
            {
                return proto::deep_copy(
                    '{' << karma::double_ << ',' << karma::double_ << '}');
            }
        };
    }}}

Some usage examples of `auto_` generators:

Emit a simple string using the `karma::string` generator:

    test_generator_attr("abc", auto_, "abc");
    test_generator("abc", auto_("abc"));

Emit instances of the `complex` data type as defined above using the generator defined by the customization point for `complex`:

    test_generator_attr("{1.2,2.4}", auto_, complex(1.2, 2.4));
    test_generator("{1.2,2.4}", auto_(complex(1.2, 2.4)));