我正在使用 boost::spirit 将文本解析为包含固定大小数组的结构。按照
中的示例进行操作时并尝试使用它解析为包含 std::array (或 boost::array)的结构,我认识到由于 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 .
这是我当前的代码:
#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;
}
最佳答案
你要去的地方:)你似乎很快就达到了精神的扭曲速度。
已编辑仔细阅读问题后,我注意到您要求一种更短、更少侵入性的方式。
我不知道修复它的非侵入性方法,但如果您专门为其指定 is_container
,则可以使用 boost::array
。
这非常不具有干扰性,但仍然会改变您的类型。
#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
关于c++ - boost::spirit 使用 std::array 解析为结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34435150/