The answer depends on what version of Spirit you're referring to.
Spirit.Classic (the former Spirit V1.x) implements special copy semantics for rules. The documentation says:
When a rule is referenced anywhere in
the right hand side of an EBNF
expression, the rule is held by the
expression by reference. It is the
responsibility of the client to ensure
that the referenced rule stays in
scope and does not get destructed
while it is being referenced.
The assignment operator essentially references the rhs rule without creating a deep copy as well. This was done to allow:
rule<> r1, r2;
r1 = ...;
r2 = r1;
But this turned out to be highly confusion as it prevented handling rules the same way as 'normal' objects.
For that reason there was the member function rule::copy()
, allowing to make explicit deep copies of a rule (for instance to store them in an STL container).
At the same time this:
r2 = r1.copy();
is plain wrong. r2
would refer to the (destructed) temporary copy of r1
returned from the function copy()
.
In Spirit.Qi (i.e. Spirit V2.x) the behaviour is partially changed. rules are now behaving as expected when handled outside of parsers. You can store them normally in containers (the assignment operator exposes the expected behavior). But beware, that inside a parser expression rules are still held by reference, which still allows to refer to a rule the same way as before:
rule<> r1, r2;
r1 = ... >> r2 >> ...;
r2 = ... >> r1 >> ...;
Sometimes it's necessary to make a deep copy of a rule, so there is still the member functon copy
.
The changed copy semantics have another side effect. Constructs like:
r1 = r2;
are now creating a (deep) copy of r2
, which might not be what you expect, especially if r2
will get its rhs assigned only after being 'assigned' to r1
. For that reason there is the new member function alias
enabling reference semantics for this corner case:
r1 = r2.alias();
In any case, in both versions of Spirit you will end up with dangling references if part of the rules referenced from a parser expression go out of scope.
BTW, neither Spirit version implements a function rule::ref()
.