6

カルマを使用して大きな構造体の表現を生成していますが、生成中に構造体がコピーされています。私は彼らがそうである必要はないと思うので、それを避ける方法を考えていました。

以下の簡単な例では、ターゲット構造体が にコピーされるため、"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_ruleの属性を参照によって宣言することで、コピーを停止できます。

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

しかし、それはベクターでは機能しません [明らかにfoos はコピー可能ですが、ベクター構築時にコピーするのは安価かもしれませんが、生成時にコピーするのは高価です:-)]

以下の例では、'Copy!' が出力されます。生成中に 5 回 (つまり、ベクトル ctor 中のコピーを無視します)。foo_ruleの属性が参照でない場合は 10 回:

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

両方のルールで参照を取得すると、VC 2008 の Boost 1.47 でコンパイルされません。

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

と でextract_from_containerインスタンス化されAttribute = std::vector<foo>ますExposed=std::vector<foo> &。extract_from.hpp の 131 行目で、Exposed const &refrence-to-reference を作成するときに、フォームを作成しようとしてコンパイラが失敗します。

私は何かが欠けているように感じるので、どんなポインタでも大歓迎です!

4

1 に答える 1

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 with Boost 1.47.0) でテストしました。上記で動作確認済みです。std::vector<foo> my_vec_foo(5)ただし、 には5 つのコピーが作成されていることも示されているため、混乱の余地があります。コードと出力の BIG LETTER 警告を参照してください。

#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
于 2011-11-09T22:39:00.367 に答える