2015-12-23 4 views
2

Я использую boost :: spirit для разбора текста в структуру, содержащую массив фиксированного размера. Следуя примеру вboost :: spirit parsing в struct с std :: array

qi/boost_array.cpp

и пытается использовать его для разбора в структуры, содержащей зЬй :: массив (или повышающий :: массив) я признал, что из-за того, как BOOST_FUSION_ADAPT_STRUCT работ у меня есть для размещения помощника result_of :: adapt_array < some_array_type> :: type в структуре.

Я думаю, что должно быть возможно создать обертку, используя BOOST_FUSION_ADAPT_ADT, но, похоже, излишне просто избавиться от небольших накладных расходов адаптера в структуре. Поскольку у меня не так много примеров, я могу жить с ним с точки зрения памяти, но он также вводит некоторый шум.

Я также думаю, что можно создать адаптер, который получается из типа массива, а не инкапсулировать его, чтобы скрыть некоторые из шумов, но это заставит меня изменить все существующие структуры, и это приведет к утечке парсера накладных расходов наружу что не является хорошим решением.

Есть ли что-то очевидное Я приближаюсь к неправильному или существуют новые помощники, которые направляют накладные расходы в фоновом режиме, чтобы их можно было инкапсулировать в парсер?

Я знаю Using std::array as Attribute for boost::spirit::x3.

Live Example

Вот мой текущий код:

#include <string> 
#include <array> 
#include <boost/spirit/include/qi.hpp> 

namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

// ...code from http://www.boost.org/doc/libs/1_60_0/libs/spirit/example/qi/boost_array.cpp here 

typedef result_of::adapt_array<std::array<double, 6> >::type AdaptedArrayType; 

struct StructWithArray 
{ 
    StructWithArray() 
     : adaptedAry_(ary_) 
    {} 

    double dummy_; // see https://stackoverflow.com/questions/19823413/spirit-qi-attribute-propagation-issue-with-single-member-struct 
    std::array<double, 6> ary_; 
    AdaptedArrayType adaptedAry_; 
}; 

BOOST_FUSION_ADAPT_STRUCT(
    StructWithArray 
    , 
    (double, dummy_) 
    (AdaptedArrayType, adaptedAry_) 
    ) 

template <typename Iterator, typename Skipper> 
struct StructWithArrayParser 
    : qi::grammar<Iterator, StructWithArray(), Skipper> 
{ 
    StructWithArrayParser() : StructWithArrayParser::base_type(start) 
    { 
     using qi::double_; 

     arrayLine %= double_ > double_ > double_ > double_ > double_ > double_; 
     start %= double_ > arrayLine; 
    } 

    qi::rule<Iterator, AdaptedArrayType(), Skipper> arrayLine; 
    qi::rule<Iterator, StructWithArray(), Skipper> start; 
}; 

int main() { 
    std::string arrayStr = "0 1 2 3 4 5 6"; 
    std::string::const_iterator it = arrayStr.begin(); 
    std::string::const_iterator endIt = arrayStr.end(); 
    StructWithArrayParser<std::string::const_iterator, ascii::space_type> grammar; 
    StructWithArray structWithArray; 
    bool ret = phrase_parse(it, endIt, grammar, ascii::space, structWithArray); 
    return 0; 
} 

ответ

2

Вы собираетесь места :) Вы, кажется, достигли скорости варп с Духом в кратчайшие сроки.

EDITED После прочтения вопроса ближе я заметил, что вы просите более короткий, менее навязчивый путь.

Я не знаю, нет навязчивого способа исправить это, но вы можете использовать boost::array, если вы специализируетесь на is_container.

Это довольно неинтрузивно, но по-прежнему меняет ваши типы.

Live On Coliru

#include <boost/fusion/include/tuple.hpp> 
#include <boost/fusion/adapted/boost_array.hpp> 
#include <boost/spirit/include/qi.hpp> 
#include <string> 

namespace boost { namespace spirit { namespace traits { 
    template <typename T, size_t N> 
     struct is_container<boost::array<T, N>, void> : mpl::false_ { }; 
} } } 

namespace qi = boost::spirit::qi; 
namespace ascii = boost::spirit::ascii; 

struct StructWithArray 
{ 
    double dummy_; // see http://stackoverflow.com/questions/19823413/spirit-qi-attribute-propagation-issue-with-single-member-struct 
    boost::array<double, 6> ary_; 
}; 

BOOST_FUSION_ADAPT_STRUCT(StructWithArray, dummy_, ary_) 

template <typename Iterator, typename Skipper> 
struct StructWithArrayParser 
    : qi::grammar<Iterator, StructWithArray(), Skipper> 
{ 
    StructWithArrayParser() : StructWithArrayParser::base_type(start) 
    { 
     using qi::double_; 

     arrayLine = double_ > double_ > double_ > double_ > double_ > double_; 
     start  = double_ > arrayLine; 
    } 

    private: 
    qi::rule<Iterator, boost::array<double, 6>(), Skipper> arrayLine; 
    qi::rule<Iterator, StructWithArray(), Skipper> start; 
}; 

int main() { 
    std::string arrayStr = "0 1 2 3 4 5 6"; 
    using It = std::string::const_iterator; 
    It it = arrayStr.begin(), endIt = arrayStr.end(); 
    StructWithArrayParser<It, ascii::space_type> grammar; 

    StructWithArray structWithArray; 
    bool ret = phrase_parse(it, endIt, grammar, ascii::space, structWithArray); 
    std::cout << std::boolalpha << ret << "\n"; 

    for (double v : structWithArray.ary_) 
     std::cout << v << " "; 
} 

Печать:

true 
1 2 3 4 5 6 
+0

После проверки всех перестановок '{г ++, звоном ++} -std = {C++ 03, C++ 11, гр ++ 14} 'с boost 1.58,59,60 Я выяснил, что неверно понял вопрос. В ближайшее время – sehe

+1

Обновлен ответ с наилучшим обходным решением, которое я мог (легко) достичь. Мне кажется, вы могли бы с этим справиться, чтобы имитировать то же самое с 'std :: array', но он не готов – sehe

+0

Фантастический обходной способ :) Именно то, на что я надеялся. Я могу с радостью жить с boost :: array, но сделаю редактирование, если у меня найдется время, чтобы заставить его работать с std :: array. Также замечательно, что ваше решение указало мне на BOOST_PP_VARIADICS; так проще. –

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

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