1

我正在尝试创建一个由多个规则组成的 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 时遇到相同的错误。

主文件

#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);
4

1 回答 1

1

正如cv_and_he所说,我错误地使用了 omit 。我伸出手来告诉我的一位老同事也是这样。更正后的代码如下。

主文件

#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;
}
于 2015-02-20T02:25:00.647 回答