[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
5.1.2 Accessing subexpressions
Many GiNaC classes, like add
, mul
, lst
, and
function
, act as containers for subexpressions. For example, the
subexpressions of a sum (an add
object) are the individual terms,
and the subexpressions of a function
are the function's arguments.
GiNaC provides several ways of accessing subexpressions. The first way is to use the two methods
size_t ex::nops(); ex ex::op(size_t i); |
nops()
determines the number of subexpressions (operands) contained
in the expression, while op(i)
returns the i
-th
(0..nops()-1
) subexpression. In the case of a power
object,
op(0)
will return the basis and op(1)
the exponent. For
indexed
objects, op(0)
is the base expression and op(i)
,
i>0 are the indices.
The second way to access subexpressions is via the STL-style random-access
iterator class const_iterator
and the methods
const_iterator ex::begin(); const_iterator ex::end(); |
begin()
returns an iterator referring to the first subexpression;
end()
returns an iterator which is one-past the last subexpression.
If the expression has no subexpressions, then begin() == end()
. These
iterators can also be used in conjunction with non-modifying STL algorithms.
Here is an example that (non-recursively) prints the subexpressions of a given expression in three different ways:
{ ex e = ... // with nops()/op() for (size_t i = 0; i != e.nops(); ++i) cout << e.op(i) << endl; // with iterators for (const_iterator i = e.begin(); i != e.end(); ++i) cout << *i << endl; // with iterators and STL copy() std::copy(e.begin(), e.end(), std::ostream_iterator<ex>(cout, "\n")); } |
op()
/nops()
and const_iterator
only access an
expression's immediate children. GiNaC provides two additional iterator
classes, const_preorder_iterator
and const_postorder_iterator
,
that iterate over all objects in an expression tree, in preorder or postorder,
respectively. They are STL-style forward iterators, and are created with the
methods
const_preorder_iterator ex::preorder_begin(); const_preorder_iterator ex::preorder_end(); const_postorder_iterator ex::postorder_begin(); const_postorder_iterator ex::postorder_end(); |
The following example illustrates the differences between
const_iterator
, const_preorder_iterator
, and
const_postorder_iterator
:
{ symbol A("A"), B("B"), C("C"); ex e = lst(lst(A, B), C); std::copy(e.begin(), e.end(), std::ostream_iterator<ex>(cout, "\n")); // {A,B} // C std::copy(e.preorder_begin(), e.preorder_end(), std::ostream_iterator<ex>(cout, "\n")); // {{A,B},C} // {A,B} // A // B // C std::copy(e.postorder_begin(), e.postorder_end(), std::ostream_iterator<ex>(cout, "\n")); // A // B // {A,B} // C // {{A,B},C} } |
Finally, the left-hand side and right-hand side expressions of objects of
class relational
(and only of these) can also be accessed with the
methods
ex ex::lhs(); ex ex::rhs(); |
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |