Boost:: Spirit парсинг в структуру с помощью std::array
Я использую boost:: spirit для разбора текста в структуру, содержащую массив фиксированного размера. Следуя примеру в
и пытаясь использовать его для разбора в структуру, содержащую std::array (или boost::array), я понял, что из-за того, как работает BOOST_FUSION_ADAPT_STRUCT, я должен поместить вспомогательный тип result_of::adapt_array
Я думаю, что можно создать оболочку, используя BOOST_FUSION_ADAPT_ADT, но это кажется излишним, просто чтобы избавиться от небольших накладных расходов адаптера в структуре. Поскольку у меня не так много примеров этого, я могу жить с этим с точки зрения памяти, но это также вносит некоторый шум.
Я также думаю, что было бы возможно создать адаптер, который наследуется от типа массива, а не инкапсулирует его, чтобы скрыть часть шума, но это заставило бы меня изменить все существующие структуры, и это привело бы к утечке служебных данных парсера наружу, что не является Хорошее решение.
Есть ли что-то очевидное, что я ошибаюсь, или существуют новые помощники, которые направляют служебные данные в фоновом режиме, чтобы их можно было инкапсулировать в анализаторе?
Мне известно об использовании std:: array в качестве атрибута для boost:: spirit:: x3.
Вот мой текущий код:
#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://stackru.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;
}
1 ответ
Ты идешь куда-то:) Ты, кажется, достиг скорости деформации с Духом в кратчайшие сроки.
Отредактированный После прочтения вопроса ближе я заметил, что вы просите более короткий, менее навязчивый способ.
Я не знаю ненавязчивый способ исправить это, но вы можете использовать boost::array
если вы специализируетесь is_container
для этого.
Это довольно ненавязчиво, но все же меняет ваши типы.
#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://stackru.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