boost::spirit 使用 std::array 解析为结构

boost::spirit parsing into struct with std::array

我正在使用 boost::spirit 将文本解析为包含固定大小数组的结构。遵循

中的示例

qi/boost_array.cpp

并尝试使用它来解析包含 std::array(或 boost::array)的结构,我认识到这是因为 BOOST_FUSION_ADAPT_STRUCT 工作我必须将助手 result_of::adapt_array< some_array_type >::type 也放在结构中。

我认为应该可以使用 BOOST_FUSION_ADAPT_ADT 创建一个包装器,但是仅仅为了摆脱结构中的小适配器开销似乎有点过分了。因为我没有很多实例,所以从内存的角度来看我可以接受它,但它也会引入一些噪音。

我还认为可以创建一个从数组类型派生的适配器而不是封装它来隐藏一些噪音,但它会迫使我改变所有现有的结构并且它会将解析器开销泄漏给外面不是一个好的解决方案。

是否有明显的错误,或者是否存在新的帮助程序将开销路由到后台以便将它们封装在解析器中?

我知道 .

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

这很简单,但仍然会改变您的类型。

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