I'm using karma to generate representations of large structs, but the structs are being copied during generation. I don't think they need to be, so was wondering how to avoid it.
The quick example below prints "Copy!", as the target struct is copied in rule::generate
:
namespace karma = spirit::karma;
namespace phoenix = boost::phoenix;
struct foo
{
foo() { }
foo( foo const &other ) { std::cout << "Copy!"; }
int f() const { return 42; }
};
std::string output;
typedef std::back_insert_iterator< std::string > iterator;
karma::rule< iterator, foo() > foo_rule =
karma::int_[ karma::_1 = phoenix::bind( &foo::f, karma::_val ) ];
foo my_foo;
iterator it( output );
karma::generate( it, foo_rule, my_foo );
I can stop the copy by declaring foo_rule
's attribute by reference:
karma::rule< iterator, foo &() > foo_rule
but that doesn't work with a vector [obviously the foo
s are therefore copyable, but may be cheap to copy at vector construction, but expensive to copy at generate time :-)]
The example below prints 'Copy!' five times during generation (that is, ignoring copies during vector ctor); 10 times if foo_rule
's attribute isn't a reference:
std::vector<foo> my_vec_foo(5);
karma::rule< iterator, std::vector<foo>() > vec_foo_rule = *foo_rule;
karma::generate(it, vec_foo_rule, my_vec_foo);
Having both rules take references doesn't compile with Boost 1.47 on VC 2008. That is, with:
karma::rule< iterator, foo &() > foo_rule /* = ... */;
karma::rule< iterator, std::vector<foo> &() > vec_foo_rule /* = ... */;
I get extract_from_container
instantiated with Attribute = std::vector<foo>
and Exposed=std::vector<foo> &
. On line 131 of extract_from.hpp, it tries to form Exposed const &
and the compiler fails when creating refrence-to-reference.
I feel like I'm missing something, so any pointers would be greatly appreciated!