...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
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.
// forwards to <boost/spirit/home/karma/auto.hpp> #include <boost/spirit/include/karma_auto.hpp>
Also, see Include Structure.
Name |
---|
|
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_
).
Semantics of an expression is defined only where it differs from, or is
not defined in PrimitiveGenerator
.
Expression |
Description |
---|---|
|
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). |
|
Create a generator instance compatible with the supplied literal value. This generator never fails (unless the underlying output stream reports an error). |
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 |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Any string ( |
|
Any (STL) container |
Kleene Star (unary |
Any Fusion sequence |
Sequence operator ( |
|
Optional operator (unary |
|
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.
Expression |
Attribute |
---|---|
|
|
|
|
Important | |
---|---|
The attribute type |
Note | |
---|---|
In addition to their usual attribute of type |
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.
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/phoenix/core.hpp> #include <boost/phoenix/operator.hpp> #include <boost/fusion/include/std_pair.hpp> #include <boost/proto/deep_copy.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)));