2016-03-20 13 views
5

私はバイソンの意味値からパーズデータ構造を構築するために取り組んでいます。 1つの特定の構造は、タイプstd::vector<double>である。私は、バイソンの内部が動くセマンティック値をどのように扱うのか不思議です。 。私はC++のm4ファイルを分析してみました、とが見つかりました:バイソン値の移動/効率

template <typename Base> 
    inline 
    void 
    ]b4_parser_class_name[::basic_symbol<Base>::move (basic_symbol& s) 
    { 
    super_type::move(s); 
    ]b4_variant_if([b4_symbol_variant([this->type_get()], [value], [move], 
             [s.value])], 
        [value = s.value;])[]b4_locations_if([ 
    location = s.location;])[ 
    } 

残念ながら、私はほぼ十分なのstd ::ベクトルのようなデータ構造を移動の効率を作るために、これを解読することができない、一部の自分の無知のためにm4の構文。

は私の文法でこれを考える:

%define api.token.constructor 
%define api.value.type variant 
%type < std::vector<double> > numlist 
... 
numlist: 
    num    { $$ = std::vector<double>(); $$.push_back($1); } 
| numlist "," num { $$ = $1; $$.push_back($3); } 
; 

私はパフォーマンスへの影響の不確実です。これは、C++コンパイラではなくC++コンパイラでコンパイルされます。したがって、移動のセマンティクスはありません。

私は$$ = std::vector<double>()ステートメントを削除できたと推測しています。私はそれがすでにデフォルトで構築されていると想定していますが、テストしていないので、バイソンの内部バリアント型の仕組みがわかりません。私が特に関心を持っているのは、$$ = $1; $$.push_back($3);です。追加されるすべてのアイテムに対してベクターがコピーされますか?

これは、タイプをstd::vector<double> *に切り替える場合であるかどうかを判断できません。確かに、バイソンのバリアント型の背後にある理由の多くは、ポインタの集合体の代わりにプレーンなC++型を使用することでした。


私はまた、C++ 11月14日、特にstd::unique_ptrを利用して、実際にないパーサに同様の好奇心を持っていました。例えば、$$ = std::make_unique<...>(...)というように、左回帰規則の1行が割り当てられている場合、$$ = $1; $$->...は次のようになりますか?

答えて

1

私ははっきりとバイソン/ Yaccの専門家ではないよしかし、あなたが生成されたコードを見ることができます:parser::parseメソッドの内部で、どこyylhsはタイプstack_symbol_typeのローカル変数であるとyystack_が属性である産む

 { 
    case 2: 
#line 20 "test.yy" // lalr1.cc:846 
    { yylhs.value.as< std::vector<double> >() = std::vector<double>(); 
     yylhs.value.as< std::vector<double> >().push_back(yystack_[0].value.as<double>()); } 
#line 1306 "test.tab.cc" // lalr1.cc:846 
    break; 

    case 3: 
#line 21 "test.yy" // lalr1.cc:846 
    { yylhs.value.as< std::vector<double> >() = yystack_[2].value.as< std::vector<double> >(); 
     yylhs.value.as< std::vector<double> >().push_back(yystack_[0].value.as<double>()); } 
#line 1312 "test.tab.cc" // lalr1.cc:846 
    break; 

タイプstack_typestack_symbol_typeを含む)のparserクラスのものです。

はいのように見えますが、$$ = $1を実行すると全体のベクトルがコピーされますが、コンパイラがこれを最適化する方法はわかりません。またconstバリアントで

template <typename T> 
T& as(); 

、そう気取りはあなたのケースでstd::vector<double>あるので、コピーが作成されるタイプT、上で行われます。asの宣言は次のようです。 c++11移動セマンティクスを使用したとしても、RHSがxvalueではないため、コピーが作成されていました。

+0

ありがとうございます!私は本当にポインタからベクトルへの構築を避けたいと思っていましたが、それは最善の方法です。 – Zac

+1

@ Zacあなたは$ 1と$$を入れ替えることを検討しましたか? –

+0

@Michael私はしていませんでした。 std :: swap()を参照していますか? – Zac

関連する問題