C++ 使用业力生成器避免属性副本

C++ 使用业力生成器避免属性副本,c++,boost-spirit,boost-spirit-karma,C++,Boost Spirit,Boost Spirit Karma,我正在使用生成大型结构的表示,但在生成过程中复制了结构。我不认为他们需要,所以我想知道如何避免它 下面的快速示例打印“复制!”,因为目标结构是在rule::generate中复制的: namespace karma = spirit::karma; namespace phoenix = boost::phoenix; struct foo { foo() { } foo( foo const &other ) { std::cout << "Copy!";

我正在使用生成大型结构的表示,但在生成过程中复制了结构。我不认为他们需要,所以我想知道如何避免它

下面的快速示例打印“复制!”,因为目标结构是在
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
s因此是可复制的,但在向量构造时复制成本可能较低,但在生成时复制成本较高:-)]

下面的示例打印“复制!”生成过程中五次(即,在矢量计算过程中忽略副本);如果
foo_rule
的属性不是引用,则执行10次:

karma::rule< iterator, foo &() > 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);
std::vector my_vec_foo(5);
karma::rulevec_foo_rule=*foo_rule;
因果报应:产生(它,维克福规则,我的维克福);
让这两个规则都引用并不能在VC 2008上用Boost 1.47编译。即:

karma::rule< iterator, foo &() > foo_rule /* = ... */;
karma::rule< iterator, std::vector<foo> &() > vec_foo_rule /* = ... */;
karma::rulefoo_rule/*=…*/;
karma::rulevec_foo_rule/*=…*/;
我使用
属性=std::vector
暴露=std::vector&
从容器中获取
提取Exposed const&
,编译器在创建引用时失败


我觉得我遗漏了什么,所以任何指点都将不胜感激

我肯定你已经试过了,但我还是要说。您是否尝试过以下方法:

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对于优秀的极小问题。也许,你可以让它更具复制性/可复制性(目前,对精神缺乏深入了解的人不太可能让它运行)。我测试了我的答案,这篇文章包含了一个完整的最小样本。干杯这五个副本应该是清晰的,因为这就是调整大小(和特殊ctor)的工作原理。它们默认构造一个元素作为第二个参数,并将其复制到所有保留的插槽中。@Xeo:你认为我应该解释一下吗?我认为这是显而易见的:)我只是想向任何可能感到疑惑的人指出这一点。:)另外,您的示例缺少一些include,并且似乎无法在Ideone上编译。似乎他们使用的增强版本太低了。@Xeo:“缺少包含”似乎措辞有点强硬。这是一个风格问题:我碰巧知道(在linux上)所有的间接头都存在,因此更喜欢简洁。请注意,OP遗漏了更多(关键的)内容。这些很难找到。最后,我从未承诺它能在ideone上工作:)(我不知道为什么它很重要)哦,其实这并不重要,我只是想看看发电机的确切输出,因为我决定在不久的将来进一步了解Spirit。:)
#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);
}
Copy!
Copy!
Copy!
Copy!
Copy!

START WATCHING NOW