...one of the most highly
regarded and expertly designed C++ library projects in the
world. — Herb Sutter and Andrei
consumes the attribute type of the embedded generator without generating
any output. The
omit directive will still execute the embedded
generator while discarding the generated output afterwards. The
directive will not execute the embedded generator, but will use it only
to extract the exposed attribute type.
// forwards to <boost/spirit/home/karma/directive/omit.hpp> #include <boost/spirit/include/karma_omit.hpp>
Also, see Include Structure.
A generator object
Attribute type of generator
Semantics of an expression is defined only where it differs from, or
is not defined in
See Compound Attribute Notation.
a: A --> omit[a]: A a: Unused --> omit[a]: Unused
a: A --> skip[a]: A a: Unused --> skip[a]: Unused
The overall complexity of the
omitdirective depends on the complexity of the embedded generator. The overall complexity of the
skipgenerator directive is O(1) as it does not generate any output.
The test harness for the example(s) below is presented in the Basics Examples section.
#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::double_; using boost::spirit::karma::omit;
Basic usage of a
generator directive. It shows how it consumes the first element of the
provided attribute without generating anything, leaving the second element
of the attribute to the non-wrapped
std::pair<double, double> p (1.0, 2.0); test_generator_attr("2.0", omit[double_] << double_, p);
Generally, this directive is helpful in situations, where the attribute
type contains more information (elements) than need to be used to generate
the required output. Normally in such situations we would resolve to
use semantic actions to explicitly pass the correct parts of the overall
attribute to the generators. The
directive helps achieving the same without having to use semantic actions.
Consider the attribute type:
typedef fusion::vector<int, double, std::string> attribute_type;
where we need to generate output only from the first and last element:
typedef std::back_insert:iterator<std::string> iterator_type; karma::rule<iterator_type, attribute_type()> r; r = int_[_1 = phoenix::at_c<0>(_val)] << string[_1 = phoenix::at_c<2>(_val)]; std::string str; iterator_type sink(str); generate(sink, r, attribute_type(1, 2.0, "example")); // will generate: '1example'
This is error prone and not really readable. The same can be achieved
by using the
r = int_ << omit[double_] << string;
which is at the same time more readable and more efficient as we don't have to use semantic actions.
The semantics of using the
skip directive are identical to the
directive, except that it does not actually execute the embedded generator.
For this reason it is usually preferable to utilize the
directive instead of the
omit directive. On the other hand, the
directive is very useful whenever the embedded generator produces side
effects (has semantic actions which need to be executed).