I am trying to create a Spirit Karma grammar that is composed of several rules. This grammar is intended to create a string of the format "(0, 1, 2, 3), (4, 5, 6, 7), (8, 9, 10, 11)". The rule to print out each individual struct that I call RowData uses BOOST_FUSION_ADAPT_STRUCT to print out all of the fields of that struct. If the grammar only includes that rule, the grammar works fine. However, I am using this struct as the value of a std::map. The key in an integer but I do not care about that value and want to drop it. I have created rules to parse the std::map but the rule that handles the std::pair fails to compile for a BOOST_SPIRIT_ASSERT_MATCH. I have created a small bit of code that generates this issue. The line is pairRule = bs::karma::omit << rowDataRule;
If anybody has an idea what the issue is or how I could do this differently, I would appreciate the help.
Edit: I am using gcc 4.8.3 on OpenSUSE 13.2 but get the same error with gcc 4.8.2 on Ubuntu 14.04 LTS.
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;
}
Error message:
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);
As cv_and_he said, I was using omit incorrectly. An old coworker I reached out to told me the same. The corrected code is below.
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;
}