Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

{qi,karma}::symbols copy constructor does not make an independent copy #760

Open
jwwalker opened this issue Apr 4, 2023 · 2 comments
Open

Comments

@jwwalker
Copy link

jwwalker commented Apr 4, 2023

In Boost 1.82.0 beta 1, the following code

#include <boost/spirit/include/qi.hpp>
#include <iostream>

int main(int argc, const char * argv[])
{
	boost::spirit::qi::symbols<char, int>	one;
	one.at("x") = 1;
	one.at("y") = 2;

	boost::spirit::qi::symbols<char, int>	two( one );
	two.at("x") = 3;
	
	std::cout << "In one, x = " << one.at("x") <<
		", y = " << one.at("y") << std::endl;
	
	return 0;
}

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 assignment two = one, things behave as expected.

@Kojoley
Copy link
Collaborator

Kojoley commented Apr 4, 2023

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 Kojoley changed the title qi::symbols copy constructor does not make an independent copy {qi,karma}::symbols copy constructor does not make an independent copy Apr 4, 2023
@sehe
Copy link

sehe commented Oct 13, 2023

@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]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants