...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
The real_generator
can
generate real numbers of arbitrary length and size limited by its template
parameter, Num
. The numeric
base type Num
can be
a user defined numeric type such as fixed_point (fixed point reals) and
bignum (unlimited precision numbers) if the type follows certain expression
requirements (for more information about the requirements, see below).
// forwards to <boost/spirit/home/karma/numeric/real.hpp> #include <boost/spirit/include/karma_real.hpp>
Also, see Include Structure.
Name |
---|
|
|
|
|
Note | |
---|---|
|
template <typename Num, typename RealPolicies> struct real_generator;
Parameter |
Description |
Default |
---|---|---|
|
The type of the real number to generate. |
|
|
The policies to use while converting the real number. |
|
For more information about the type RealPolicies
see below.
Notation
num
Numeric literal, any real number value, or a Lazy
Argument that evaluates to a real number value of type
Num
Num
Type of num
: any
real number type
Semantics of an expression is defined only where it differs from, or
is not defined in PrimitiveGenerator
.
Expression |
Semantics |
---|---|
|
Generate the real number literal |
float_ double_ long_double
|
Generate the real number provided by a mandatory attribute
using the default formatting (no trailing zeros, |
float_(num) double_(num) long_double(num)
|
Generate the real point number provided by the immediate literal
value the generator is initialized from using the default formatting
(no trailing zeros, |
All generators listed in the table above (except lit(num)
) are predefined specializations of the
real_generator<Num, RealPolicies>
basic real number generator type described below. It is possible to directly
use this type to create real number generators using a wide range of
formatting options.
Expression |
Semantics |
---|---|
real_generator< Num, RealPolicies >()
|
Generate the real number of type |
real_generator< Num, RealPolicies >()(num)
|
Generate the real number of type |
The following list enumerates the requirements which must be met in order
to use a certain type Num
to instantiate a real_generator<Num, Policies>
.
In order to be usable as the first template parameter for real_generator<>
the type Num
must have
defined:
<
,
<=
, ==
, !=
,
>
, and >=
+
,
-
, /
,
*
, and %
std::fmod
, std::pow
,
std::log10
, std::lround
,
std::ltrunc
, std::modf
,
std::floor
, and std::ceil
.
These need to be defined in a way so that they will be found using
argument dependent lookup (ADL).
std::numeric_limits<Num>
allowing for numeric property
inspection.
Expression |
Attribute |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
real_generator< Num, Policies >()
|
|
real_generator< Num, Policies >()(num)
|
|
Note | |
---|---|
In addition to their usual attribute of type |
If special formatting of a real number is needed, overload the policy
class real_policies<Num>
and use it as a template parameter to the real_generator<>
real number generator. For instance:
// define a new real number formatting policy template <typename Num> struct scientific_policy : real_policies<Num> { // we want the numbers always to be in scientific format static int floatfield(Num n) { return fmtflags::scientific; } }; // define a new generator type based on the new policy typedef real_generator<double, scientific_policy<double> > science_type; science_type const scientific = science_type(); // use the new generator generate(sink, science_type(), 1.0); // will output: 1.0e00 generate(sink, scientific, 0.1); // will output: 1.0e-01
The template parameter Num
should be the type to be formatted using the overloaded policy type.
At the same time Num
will be used as the attribute type of the created real number generator.
A real number formatting policy should expose the following variables and functions:
Expression |
Description |
---|---|
template <typename Inserter , typename OutputIterator , typename Policies> bool call (OutputIterator& sink, Num n , Policies const& p);
|
This is the main function used to generate the output for a
real number. It is called by the real generator in order to
perform the conversion. In theory all of the work can be implemented
here, but the easiest way is to use existing functionality
provided by the type specified by the template parameter template <typename Inserter, typename OutputIterator , typename Policies> static bool call (OutputIterator& sink, Num n, Policies const& p) { return Inserter::call_n(sink, n, p); }
|
bool force_sign(Num n);
|
The default behavior is to not to require generating a sign.
If the function
|
bool trailing_zeros(Num n);
|
Return whether trailing zero digits have to be emitted in the
fractional part of the output. If set, this flag instructs
the real number generator to emit trailing zeros up to the
required precision digits (as returned by the
|
int floatfield(Num n);
|
Decide, which representation type to use in the generated output.
By default all numbers having an absolute value of zero or
in between
The
The return value has to be either |
unsigned precision(Num n);
|
Return the maximum number of decimal digits to generate in the fractional part of the output.
Note: If the trailing_zeros
flag is not in effect additional semantics apply. See the description
for the |
template <typename OutputIterator> bool integer_part(OutputIterator& sink , Num n, bool sign, bool force_sign);
|
This function is called to generate the integer part of the real number.
The return value defines the outcome of the whole generator.
If it is |
template <typename OutputIterator> bool dot(OutputIterator& sink, Num n, unsigned precision);
|
This function is called to generate the decimal point.
This is given to allow to decide, whether a decimal point has to be generated at all.
Note: If the
The return value defines the outcome of the whole generator.
If it is |
template <typename OutputIterator> bool fraction_part(OutputIterator& sink, Num n , unsigned adjprec, unsigned precision);
|
This function is called to generate the fractional part of the number.
Note: If
The missing preceding zeros in the fractional part have to be supplied by the implementation of this policy function.
The return value defines the outcome of the whole generator.
If it is |
template <typename CharEncoding, typename Tag, typename OutputIterator> bool exponent( OutputIterator& sink, long n);
|
This function is called to generate the exponential part of
the number (this is called only if the
The template parameters
The return value defines the outcome of the whole generator.
If it is |
template <typename CharEncoding , typename Tag, typename OutputIterator> bool nan (OutputIterator& sink, Num n , bool force_sign);
|
This function is called whenever the number to print is a non-normal
real number of type
The template parameters
The return value defines the outcome of the whole generator.
If it is |
template <typename CharEncoding , typename Tag, typename OutputIterator> bool inf (OutputIterator& sink, Num n , bool force_sign);
|
This function is called whenever the number to print is a non-normal
real number of type
The template parameters
The return value defines the outcome of the whole generator.
If it is |
Tip | |
---|---|
The easiest way to implement a proper real number formatting policy
is to derive a new type from the type |
O(N), where
N
is the number of digits needed to represent the generated real number.
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::double_; using boost::spirit::karma::lit;
Basic usage of an double_
generator:
test_generator("2.0", lit(2.0)); test_generator("2.0", double_(2)); test_generator_attr("2.0", double_(2.0), 2.0); test_generator_attr("", double_(2.0), 3.0); // fails (as 2.0 != 3.0)! test_generator_attr("-2.0", double_, -2.0); test_generator_attr("1.234e05", double_, 1234.0e2); test_generator_attr("1.234e-06", double_, 0.000001234);