Ответ зависит от того, на какую версию Духа вы ссылаетесь.
Spirit.Classic (прежний Spirit V1.x) реализует специальную семантику копирования для правил. В документации написано:
Когда на правило ссылаются где-либо в
правая сторона EBNF
выражение, правило проводится
выражение по ссылке. Это
ответственность клиента за обеспечение
что указанное правило остается в
размах и не разрушается
пока на него ссылаются.
Оператор присваивания, по сути, ссылается на правило rhs, не создавая и глубокую копию. Это было сделано для того, чтобы:
rule<> r1, r2;
r1 = ...;
r2 = r1;
Но это оказалось очень запутанным, поскольку не позволяло обрабатывать правила так же, как «обычные» объекты.
По этой причине существовала функция-член rule::copy()
, позволяющая делать явные глубокие копии правила (например, хранить их в контейнере STL).
В то же время это:
r2 = r1.copy();
просто неправильно. r2
будет означать (уничтоженную) временную копию r1
, возвращенную функцией copy()
.
В Spirit.Qi (то есть Spirit V2.x) поведение частично изменено. правила теперь ведут себя как положено, когда обрабатываются вне анализаторов. Вы можете хранить их обычно в контейнерах (оператор присваивания демонстрирует ожидаемое поведение). Но имейте в виду, что внутри выражения синтаксического анализатора все еще хранятся ссылки, что позволяет ссылаться на правило так же, как и раньше:
rule<> r1, r2;
r1 = ... >> r2 >> ...;
r2 = ... >> r1 >> ...;
Иногда необходимо сделать глубокую копию правила, поэтому функция члена все еще существует copy
.
Измененная семантика копирования имеет еще один побочный эффект. Конструирует как:
r1 = r2;
теперь создает (глубокую) копию r2
, которая может не соответствовать вашим ожиданиям, особенно если r2
получит свои rhs только после «назначения» на r1
. По этой причине есть новая функция-член alias
, разрешающая семантику ссылок для этого углового случая:
r1 = r2.alias();
В любом случае, в обеих версиях Spirit вы получите висячие ссылки, если часть правил, на которые ссылается выражение синтаксического анализатора, выйдет из области видимости.
Кстати, ни одна из версий Spirit не реализует функцию rule::ref()
.