Open jwwalker opened 1 year ago
It is might be in 'fix and find out' area because proto::deep_copy/BOOST_AUTO/qi::auto will start to do an actual copy then.
A workaround:
boost::spirit::qi::symbols<char, int> two;
two = one;
@Kojoley The copy assignment also doesn't make a deep copy. I answered a similar question Apr 6 2023 on the mailing list:
It's by design, likely to make it efficient and easy (without surprises!) to use symbols in parser expressions. In effect, they get "reference semantics" just like
qi::rule<>
does when embedded in other rules.You can easily deep-clone a symbol table if you need:
template <typename Sym> Sym clone_syms(Sym const& i) { Sym o; i.for_each(o.add); return o; }
Here's a live demo driving home the points with more examples: http://coliru.stacked-crooked.com/a/263d22bc47d63375
For completeness here's that demo program with output:
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
using namespace std::placeholders;
template <typename Sym> Sym clone_syms(Sym const& i) {
Sym o;
i.for_each(o.add);
return o;
}
void print(std::string_view s, double v) { std::cout << '[' << quoted(s) << '=' << v << ']'; };
int main() {
boost::spirit::qi::symbols<char, double> syms1;
syms1.add("x", 0.0);
auto syms2 = syms1;
auto syms3 = clone_syms(syms1);
syms2.at("x") = 99.5;
syms2.add("y", 88.5);
std::cout << "\nsyms1: "; syms1.for_each(print);
std::cout << "\nsyms2: "; syms2.for_each(print);
std::cout << "\nsyms3: "; syms3.for_each(print);
}
Printing
syms1: ["x"=99.5]["y"=88.5]
syms2: ["x"=99.5]["y"=88.5]
syms3: ["x"=0]
In Boost 1.82.0 beta 1, the following code
outputs "In one, x = 3, y = 2". I don't think anyone would expect a change to the copy to affect the original. If I instead default-construct
two
and then do a copy assignmenttwo = one
, things behave as expected.