当一个规则使用BOOST_FUSION_ADAPT_STRUCT时,精神业力语法问题

时间:2015-02-17 21:47:48

标签: c++ boost-spirit boost-fusion boost-spirit-karma

我正在尝试创建一个由几个规则组成的Spirit Karma语法。该语法旨在创建格式为“(0,1,2,3),(4,5,6,7),(8,9,10,11)”的字符串。打印出我调用RowData的每个单独结构的规则使用BOOST_FUSION_ADAPT_STRUCT打印出该结构的所有字段。如果语法只包含该规则,则语法正常。但是,我使用此结构作为std :: map的值。整数中的键,但我不关心该值,并希望删除它。我已经创建了解析std :: map的规则,但是处理std :: pair的规则无法为BOOST_SPIRIT_ASSERT_MATCH编译。我创建了一小段代码来生成此问题。该行是pairRule = bs::karma::omit << rowDataRule;如果有人知道问题是什么或我如何以不同的方式做到这一点,我将不胜感激。

编辑:我在OpenSUSE 13.2上使用gcc 4.8.3,但在Ubuntu 14.04 LTS上使用gcc 4.8.2获得了相同的错误。

的main.cpp

#include <iostream>
#include <map>

#include <boost/cstdint.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/make_tuple.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/karma.hpp>

namespace bs = boost::spirit;

struct RowData
{
    RowData() :
        field0(0),
        field1(0),
        field2(0),
        field3(0)
    {
    }

    boost::uint64_t field0;
    boost::uint64_t field1;
    boost::uint64_t field2;
    boost::uint64_t field3;
};

BOOST_FUSION_ADAPT_STRUCT(
    RowData,
    (boost::uint64_t, field0)
    (boost::uint64_t, field1)
    (boost::uint64_t, field2)
    (boost::uint64_t, field3)
)

template <typename OutputIterator>
struct RowDataGrammar :
    bs::karma::grammar< OutputIterator, std::map<boost::uint64_t, RowData>() >
{
    RowDataGrammar() : RowDataGrammar::base_type(allRowsRule)
    {
        rowDataRule =
            bs::karma::lit("(") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(")");

        // I only want the value from the map. The key is dropped.
        pairRule = bs::karma::omit << rowDataRule;

        allRowsRule = pairRule % ", ";
    }

private:
    bs::karma::rule< OutputIterator, RowData() > rowDataRule;
    bs::karma::rule< OutputIterator, std::pair<boost::uint64_t, RowData>() > pairRule;
    bs::karma::rule< OutputIterator, std::map<boost::uint64_t, RowData>() >  allRowsRule;
};

int main(int argc, char** argv)
{
    std::map<boost::uint64_t, RowData> rowMap;

    RowData rowData;
    rowData.field0 = 0;
    rowData.field1 = 1;
    rowData.field2 = 2;
    rowData.field3 = 3;
    rowMap.insert(std::make_pair(10, rowData));

    rowData.field0 = 6;
    rowData.field1 = 7;
    rowData.field2 = 8;
    rowData.field3 = 9;
    rowMap.insert(std::make_pair(20, rowData));

    std::string generatedString;
    std::back_insert_iterator<std::string> sink(generatedString);
    RowDataGrammar< std::back_insert_iterator<std::string> > grammar;

    bs::karma::generate(sink, grammar, rowMap);

    std::cout << "output :" << generatedString << std::endl;
}

错误讯息:

In file included from /usr/include/boost/fusion/support/tag_of.hpp:16:0,
                 from /usr/include/boost/fusion/support/category_of.hpp:11,
                 from /usr/include/boost/fusion/adapted/struct/detail/extension.hpp:13,
                 from /usr/include/boost/fusion/adapted/struct/adapt_struct.hpp:19,
                 from karmaTest.cpp:5:
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp: In instantiation of ‘static void boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]’:
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:229:19:   required from ‘boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>& boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
karmaTest.cpp:54:18:   required from ‘RowDataGrammar<OutputIterator>::RowDataGrammar() [with OutputIterator = std::back_insert_iterator<std::basic_string<char> >]’
karmaTest.cpp:84:62:   required from here
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:185:13: error: no matching function for call to ‘assertion_failed(mpl_::failed************ (boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]::error_invalid_expression::************)(boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>))’
             BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);
             ^
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:185:13: note: candidate is:
/usr/include/boost/mpl/assert.hpp:82:5: note: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
 int assertion_failed( typename assert<C>::type );
     ^
/usr/include/boost/mpl/assert.hpp:82:5: note:   template argument deduction/substitution failed:
/usr/include/boost/spirit/home/karma/nonterminal/rule.hpp:185:13: note:   cannot convert ‘boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_)::error_invalid_expression185::assert_arg<mpl_::bool_<false>, boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l> >()’ (type ‘mpl_::failed************ (boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>::define(boost::spirit::karma::rule<OutputIterator, T1, T2, T3, T4>&, const Expr&, mpl_::false_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>; OutputIterator = std::back_insert_iterator<std::basic_string<char> >; T1 = std::pair<long unsigned int, RowData>(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::false_ = mpl_::bool_<false>]::error_invalid_expression::************)(boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_left, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::omit>, 0l>&, boost::spirit::karma::rule<std::back_insert_iterator<std::basic_string<char> >, RowData(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>)’) to type ‘mpl_::assert<false>::type {aka mpl_::assert<false>}’
             BOOST_SPIRIT_ASSERT_MATCH(karma::domain, Expr);

1 个答案:

答案 0 :(得分:1)

正如cv_and_he所说,我正在使用省略错误。我伸出手去告诉我同样的一位老同事。更正后的代码如下。

<强>的main.cpp

#include <iostream>
#include <map>

#include <boost/cstdint.hpp>
#include <boost/fusion/adapted/struct/adapt_struct.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/make_tuple.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/karma.hpp>

namespace bs = boost::spirit;

struct RowData
{
    RowData() :
        field0(0),
        field1(0),
        field2(0),
        field3(0)
    {
    }

    boost::uint64_t field0;
    boost::uint64_t field1;
    boost::uint64_t field2;
    boost::uint64_t field3;
};

BOOST_FUSION_ADAPT_STRUCT(
    RowData,
    (boost::uint64_t, field0)
    (boost::uint64_t, field1)
    (boost::uint64_t, field2)
    (boost::uint64_t, field3)
)

template <typename OutputIterator>
struct RowDataGrammar :
    bs::karma::grammar< OutputIterator, std::map<boost::uint64_t, RowData>() >
{
    RowDataGrammar() : RowDataGrammar::base_type(allRowsRule)
    {
        rowDataRule =
            bs::karma::lit("(") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(", ") <<
            bs::karma::ulong_ <<
            bs::karma::lit(")");

        // I only want the value from the map. The key is dropped.
        pairRule = bs::karma::omit[bs::karma::ulong_] << rowDataRule;

        allRowsRule = pairRule % ", ";
    }

private:
    bs::karma::rule< OutputIterator, RowData() > rowDataRule;
    bs::karma::rule< OutputIterator, std::pair<boost::uint64_t, RowData>() > pairRule;
    bs::karma::rule< OutputIterator, std::map<boost::uint64_t, RowData>() >  allRowsRule;
};

int main(int argc, char** argv)
{
    std::map<boost::uint64_t, RowData> rowMap;

    RowData rowData;
    rowData.field0 = 0;
    rowData.field1 = 1;
    rowData.field2 = 2;
    rowData.field3 = 3;
    rowMap.insert(std::make_pair(10, rowData));

    rowData.field0 = 6;
    rowData.field1 = 7;
    rowData.field2 = 8;
    rowData.field3 = 9;
    rowMap.insert(std::make_pair(20, rowData));

    std::string generatedString;
    std::back_insert_iterator<std::string> sink(generatedString);
    RowDataGrammar< std::back_insert_iterator<std::string> > grammar;

    bs::karma::generate(sink, grammar, rowMap);

    std::cout << "output :" << generatedString << std::endl;
}