2016-03-20 2 views
5

Я работаю над построением моей структуры данных синтаксиса из семантических значений бизонов. Одна конкретная структура имеет тип std::vector<double>. Мне любопытно, как внутренние зубы обрабатывают семантические значения. Я попытался проанализировать C++ m4 файла, и нашел:.Перемещение/эффективность значения Bison

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;])[ 
    } 

К сожалению, я не могу расшифровать это почти достаточно, чтобы сделать из эффективности перемещения структуры данных, как станд :: вектор, отчасти из-за мое незнание синтаксис 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++ 98, а не компилятором C++ 11; следовательно, семантики перемещения не будет.

Я предполагаю, что заявление $$ = std::vector<double>() можно удалить; Я предполагаю, что он будет построен по умолчанию уже, но я не тестировал, и я не уверен, как работает внутренний вариант бизона. Меня особенно интересует $$ = $1; $$.push_back($3); Будет ли скопирован вектор для каждого элемента, который нужно добавить?

Я не могу определить, является ли это случаем для переключения типа на std::vector<double> *; по общему признанию, большая часть аргументов по использованию варианта варианта бизона заключалась в том, чтобы использовать простые типы С ++ вместо объединения указателей.


Я также имел подобные курьезы на парсер, который делает фактически использовать C++ 11/14 и, в частности std::unique_ptr. Если назначена одна строка леворекурсивного правила, скажем $$ = std::make_unique<...>(...), можно ли сделать $$ = $1; $$->...?

ответ

1

Я явно не эксперт Bison/Yacc, но вы можете посмотреть на сгенерированный код:

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

Что лежит внутри parser::parse методов и где yylhs локальная переменная типа stack_symbol_type и yystack_ является атрибутом класса parser типа stack_type (который содержит stack_symbol_type).

Похоже, ответ да, весь вектор будет скопирован, когда вы делаете $$ = $1, я не вижу, как компилятор может оптимизировать это. Декларация as выглядит следующим образом:

template <typename T> 
T& as(); 

С также const вариант, так что притворство делается на типе T, что в вашем случае является std::vector<double>, и, таким образом, копия сделана. Даже если вы использовали семантику перемещения c++11, копия была бы сделана, потому что RHS не является xvalue.

+0

Спасибо! Я действительно хотел избежать создания конструкции с указателем на вектор, но похоже, что это лучшее, что нужно сделать. – Zac

+1

@ Zac вы считали замену '$ 1' и' $$' вместо назначения? –

+0

@ Майкл у меня не было. Вы имеете в виду std :: swap()? – Zac

 Смежные вопросы

  • Нет связанных вопросов^_^