[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
6.3.1 Print methods for classes
The method table for a class is set up either in the definition of the class,
by passing the appropriate print_func<C>()
option to
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT()
(See section Adding classes, for
an example), or at run-time using set_print_func<T, C>()
. The latter
can also be used to override existing methods dynamically.
The argument to print_func<C>()
and set_print_func<T, C>()
can
be a member function of the class (or one of its parent classes), a static
member function, or an ordinary (global) C++ function. The C
template
parameter specifies the appropriate print_context
type for which the
method should be invoked, while, in the case of set_print_func<>()
, the
T
parameter specifies the algebraic class (for print_func<>()
,
the class is the one being implemented by
GINAC_IMPLEMENT_REGISTERED_CLASS_OPT
).
For print methods that are member functions, their first argument must be of
a type convertible to a const C &
, and the second argument must be an
unsigned
.
For static members and global functions, the first argument must be of a type
convertible to a const T &
, the second argument must be of a type
convertible to a const C &
, and the third argument must be an
unsigned
. A global function will, of course, not have access to
private and protected members of T
.
The unsigned
argument of the print methods (and of ex::print()
and basic::print()
) is used for proper parenthesizing of the output
(and by print_tree
for proper indentation). It can be used for similar
purposes if you write your own output formats.
The explanations given above may seem complicated, but in practice it's really simple, as shown in the following example. Suppose that we want to display exponents in LaTeX output not as superscripts but with little upwards-pointing arrows. This can be achieved in the following way:
void my_print_power_as_latex(const power & p, const print_latex & c, unsigned level) { // get the precedence of the 'power' class unsigned power_prec = p.precedence(); // if the parent operator has the same or a higher precedence // we need parentheses around the power if (level >= power_prec) c.s << '('; // print the basis and exponent, each enclosed in braces, and // separated by an uparrow c.s << '{'; p.op(0).print(c, power_prec); c.s << "}\\uparrow{"; p.op(1).print(c, power_prec); c.s << '}'; // don't forget the closing parenthesis if (level >= power_prec) c.s << ')'; } int main() { // a sample expression symbol x("x"), y("y"); ex e = -3*pow(x, 3)*pow(y, -2) + pow(x+y, 2) - 1; // switch to LaTeX mode cout << latex; // this prints "-1+{(y+x)}^{2}-3 \frac{x^{3}}{y^{2}}" cout << e << endl; // now we replace the method for the LaTeX output of powers with // our own one set_print_func<power, print_latex>(my_print_power_as_latex); // this prints "-1+{{(y+x)}}\uparrow{2}-3 \frac{{x}\uparrow{3}}{{y} // \uparrow{2}}" cout << e << endl; } |
Some notes:
-
The first argument of
my_print_power_as_latex
could also have been aconst basic &
, the second one aconst print_context &
. -
The above code depends on
mul
objects converting their operands topower
objects for the purpose of printing. -
The output of products including negative powers as fractions is also
controlled by the
mul
class. -
The
power/print_latex
method provided by GiNaC prints square roots using\sqrt
, but the above code doesn't.
It's not possible to restore a method table entry to its previous or default
value. Once you have called set_print_func()
, you can only override
it with another call to set_print_func()
, but you can't easily go back
to the default behavior again (you can, of course, dig around in the GiNaC
sources, find the method that is installed at startup
(power::do_print_latex
in this case), and set_print_func
that
one; that is, after you circumvent the C++ member access control…).
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |