2011-11-09 44 views
6

我使用karma来生成大型结构的表示,但结构在生成过程中被复制。我不想认为他们需要,所以想知道如何避免它。避免使用属性发生器的属性副本

下方打印的快速例如“复制!”,作为目标结构也是在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); 

我可以通过声明foo_rule的属性,通过参考停止复制:

karma::rule< iterator, foo &() > foo_rule 

,但这不适用于载体[显然foo因此是可复制的,但在矢量构建时可能便宜,但在生成时复制时价格昂贵:-)]

下面的例子打印'复制!'在生成期间五次(即,在向量ctor期间忽略拷贝);如果10倍的foo_rule属性不是一个参考:

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); 

有两个规则采取的引用与升压1.47 VC的2008年也就是,不编译:

karma::rule< iterator, foo &() > foo_rule /* = ... */; 
karma::rule< iterator, std::vector<foo> &() > vec_foo_rule /* = ... */; 

我得到extract_from_containerAttribute = std::vector<foo>Exposed=std::vector<foo> &实例化。在extract_from.hpp的第131行,它试图形成Exposed const &,并且编译器在创建引用参考时失败。

我觉得我错过了什么,所以任何指针将不胜感激!

+1

+1:

#include <boost/spirit/include/karma.hpp> #include <boost/spirit/include/phoenix.hpp> namespace karma = boost::spirit::karma; namespace phoenix = boost::phoenix; struct foo { foo() { } foo(foo const &other) { std::cerr << "Copy!\n"; } int f() const { return 42; } }; int main() { std::string output; typedef std::back_insert_iterator<std::string> iterator; iterator it(output); karma::rule< iterator, foo&() > foo_rule = karma::int_[ karma::_1 = phoenix::bind(&foo::f, karma::_val) ]; foo my_foo; karma::generate(it, foo_rule, my_foo); std::vector<foo> my_vec_foo(5); std::cerr << "\nSTART WATCHING NOW" << std::endl; karma::rule< iterator, std::vector<foo>&() > vec_foo_rule = *foo_rule; karma::generate(it, vec_foo_rule, my_vec_foo); } 

输出。也许,你可以让它变得更加复制/可以被复制(现在没有精神知识的人可能不会让它运行)。我测试了我的答案,这篇文章包含了一个完整的最小样本。欢呼 – sehe

回答

3

我确定你已经尝试过了,但我会说。你试过如下:

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); 

更新我只是下面的代码片段(G ++ 4.6与升压1.47.0)进行了测试。它证实了上述的工作。但是,存在混淆的余地,因为std::vector<foo> my_vec_foo(5)也将显示5个副本。看到大字母的代码,并输出报警:优秀最小的问题

Copy! 
Copy! 
Copy! 
Copy! 
Copy! 

START WATCHING NOW 
+0

这五个副本应该清楚,因为这是如何调整大小(和特殊ctor)的工作。它们默认构造一个元素作为第二个参数并将其复制到所有保留的插槽中。 – Xeo

+0

@Xeo:你认为我应该解释一下吗?我认为这是显而易见的:) – sehe

+0

只是想指出,谁可能想知道。 :)另外,你的例子会遗漏一些包含的内容,而且它似乎没有在Ideone上编译。似乎他们使用的Boost版本太低。 – Xeo