Spirit karma grammar issue when one rule uses BOOST_FUSION_ADAPT_STRUCT - c++

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

Related

Spirit phrase_parse expects 6 arguments instead of 5

A follow up to this question Handling boost spirit expression on string. Again thanks #sehe! But when I try to wrap all the grammar and ast in the namespaces and call them from within a class, I get an error by the phrase_parse api saying its expecting 6 arguments instead of 5.
The code I'm trying to implement:
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
#include <iomanip>
#include <list>
#include <string>
namespace client { namespace ast {
struct signed_;
struct program;
using operand = boost::variant<unsigned int, bool,
boost::recursive_wrapper<signed_>,
boost::recursive_wrapper<program>>;
struct signed_ { char sign; operand operand_; };
struct operation { char operator_; operand operand_; };
struct program { operand first; std::list<operation> rest; };
}} // namespace client::ast
BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_, sign, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::operation, operator_, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::program, first, rest)
namespace client { namespace ast
{
///////////////////////////////////////////////////////////////////////////
// The AST evaluator
///////////////////////////////////////////////////////////////////////////
struct eval {
using result_type = int;
int operator()(auto const& n) const { return n; }
int operator()(operation const& x, int lhs) const {
int rhs = boost::apply_visitor(*this, x.operand_);
switch (x.operator_) {
case '+': return lhs + rhs;
case '-': return lhs - rhs;
case '*': return lhs * rhs;
case '/': return lhs / rhs;
case '|': return lhs | rhs;
case '&': return lhs & rhs;
}
BOOST_ASSERT(0);
return 0;
}
int operator()(signed_ const& x) const {
int rhs = boost::apply_visitor(*this, x.operand_);
switch (x.sign) {
case '-': return -rhs;
case '+': return +rhs;
case '!': return !rhs;
}
BOOST_ASSERT(0);
return 0;
}
int operator()(program const& x) const {
int state = boost::apply_visitor(*this, x.first);
for (auto& oper : x.rest) {
state = (*this)(oper, state);
}
return state;
}
};
}} // namespace client::ast
namespace client
{
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct calculator : qi::grammar<Iterator, ast::program(), qi::space_type> {
calculator() : calculator::base_type(expression) {
using namespace qi::labels;
expression = term >> *(qi::char_("-+|&") >> term);
term = factor >> *(qi::char_("*/!") >> factor);
str = '"' >> *~qi::char_('"') >> '"';
equality_comparison = (str >> '=' >> '=' >> str)[_val = (_1 == _2)];
inequality_comparison = (str >> '!' >> '=' >> str)[_val = (_1 != _2)];
factor = inequality_comparison | equality_comparison | qi::uint_ | qi::bool_ | qi::char_("-+!") >> factor |
'(' >> expression >> ')';
}
private:
qi::rule<Iterator, ast::program(), qi::space_type> expression, term;
qi::rule<Iterator, ast::operand(), qi::space_type> factor, equality_comparison , inequality_comparison;
qi::rule<Iterator, std::string()> str;
};
}
class Expression_handler{
public:
int Execute_expression(std::string str){
using iterator_type = std::string::const_iterator;
using calculator = client::calculator<iterator_type>;
using ast_program = client::ast::program;
using ast_eval = client::ast::eval;
calculator const calc; // Our grammar
ast_eval const eval; // Evaluates the program
ast_program program;
auto f(std::begin(str)), l(std::end(str));
bool r = phrase_parse(f, l, calc, client::qi::space, program);
if (r && f == l) {
std::cout << "\nResult: " << quoted(str) << " -> " << eval(program) << std::endl;
return (eval(program));
}
else{
std::cout << "\nFailed at: " << quoted(std::string (f, l)) << "\n";
}
return 0;
};
};
int main(){
Expression_handler exp;
exp.Execute_expression("\"abc\" == \"abc\"");
return 0;
}
The error generated for this code:
ion_handler.cpp:37:24: warning: use of ‘auto’ in parameter declaration only available with ‘-std=c++20’ or ‘-fconcepts’
37 | int operator()(auto const& n) const { return n; }
| ^~~~
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/reference.hpp: In instantiation of ‘bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<client::ast::program&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >; Attribute = client::ast::program; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, client::ast::program(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>]’:
/usr/include/boost/spirit/home/qi/parse.hpp:168:45: required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, boost::spirit::qi::skip_flag, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = client::calculator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0>; Attr = client::ast::program]’
/usr/include/boost/spirit/home/qi/parse.hpp:201:32: required from ‘bool boost::spirit::qi::phrase_parse(Iterator&, Iterator, const Expr&, const Skipper&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = client::calculator<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> > >; Skipper = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0>; Attr = client::ast::program]’
Expression_handler.cpp:114:30: required from here
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: error: no matching function for call to ‘boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, client::ast::program(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>::parse(__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<client::ast::program&, boost::fusion::nil_>, boost::spirit::locals<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >&, client::ast::program&) const’
43 | return ref.get().parse(first, last, context, skipper, attr_);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:282:14: note: candidate: ‘template<class Context, class Skipper, class Attribute> bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Context = Context; Skipper = Skipper; Attribute = Attribute; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = client::ast::program(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
282 | bool parse(Iterator& first, Iterator const& last
| ^~~~~
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:282:14: note: template argument deduction/substitution failed:
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: note: cannot convert ‘first’ (type ‘__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >’) to type ‘__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&’
43 | return ref.get().parse(first, last, context, skipper, attr_);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:333:14: note: candidate: ‘template<class Context, class Skipper, class Attribute, class Params> bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&, const Params&) const [with Context = Context; Skipper = Skipper; Attribute = Attribute; Params = Params; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = client::ast::program(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
333 | bool parse(Iterator& first, Iterator const& last
| ^~~~~
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:333:14: note: template argument deduction/substitution failed:
In file included from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:36,
from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from Expression_handler.cpp:5:
/usr/include/boost/spirit/home/qi/reference.hpp:43:35: note: candidate expects 6 arguments, 5 provided
43 | return ref.get().parse(first, last, context, skipper, attr_);
| ~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Which other argument is it expecting and how do I fix this?
Your string isn't const, so the iterator type doesn't match the one you declared. The key message is:
boost/spirit/home/qi/reference.hpp|43 col 35| note: cannot convert ‘first’ (type ‘__gnu_cxx::__normal_iterator<char*, __cxx11::basic_string<char> >’) to type ‘__gnu_cxx::__normal_iterator<const char*, __cxx11::basic_string<char> >&’
Simply add const or const&:
int Execute_expression(std::string const& str)
Or don't use auto to declare f and l:
std::string::const_iterator f = std::begin(str), l = std::end(str);
Live On Coliru
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/phoenix.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
#include <iomanip>
#include <list>
#include <string>
namespace client { namespace ast {
struct signed_;
struct program;
using operand = boost::variant<unsigned int, bool,
boost::recursive_wrapper<signed_>,
boost::recursive_wrapper<program>>;
struct signed_ { char sign; operand operand_; };
struct operation { char operator_; operand operand_; };
struct program { operand first; std::list<operation> rest; };
}} // namespace client::ast
BOOST_FUSION_ADAPT_STRUCT(client::ast::signed_, sign, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::operation, operator_, operand_)
BOOST_FUSION_ADAPT_STRUCT(client::ast::program, first, rest)
namespace client { namespace ast
{
///////////////////////////////////////////////////////////////////////////
// The AST evaluator
///////////////////////////////////////////////////////////////////////////
struct eval {
using result_type = int;
int operator()(auto const& n) const { return n; }
int operator()(operation const& x, int lhs) const {
int rhs = boost::apply_visitor(*this, x.operand_);
switch (x.operator_) {
case '+': return lhs + rhs;
case '-': return lhs - rhs;
case '*': return lhs * rhs;
case '/': return lhs / rhs;
case '|': return lhs | rhs;
case '&': return lhs & rhs;
}
BOOST_ASSERT(0);
return 0;
}
int operator()(signed_ const& x) const {
int rhs = boost::apply_visitor(*this, x.operand_);
switch (x.sign) {
case '-': return -rhs;
case '+': return +rhs;
case '!': return !rhs;
}
BOOST_ASSERT(0);
return 0;
}
int operator()(program const& x) const {
int state = boost::apply_visitor(*this, x.first);
for (auto& oper : x.rest) {
state = (*this)(oper, state);
}
return state;
}
};
}} // namespace client::ast
namespace client
{
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct calculator : qi::grammar<Iterator, ast::program(), qi::space_type> {
calculator() : calculator::base_type(expression) {
using namespace qi::labels;
expression = term >> *(qi::char_("-+|&") >> term);
term = factor >> *(qi::char_("*/!") >> factor);
str = '"' >> *~qi::char_('"') >> '"';
str_eq = (str >> "==" >> str)[_val = (_1 == _2)];
str_neq = (str >> "!=" >> str)[_val = (_1 != _2)];
factor = str_neq | str_eq | qi::uint_ | qi::bool_ |
qi::char_("-+!") >> factor | '(' >> expression >> ')';
}
private:
qi::rule<Iterator, ast::program(), qi::space_type> expression, term;
qi::rule<Iterator, ast::operand(), qi::space_type> factor, str_eq, str_neq;
qi::rule<Iterator, std::string()> str;
};
}
struct Expression_handler {
static int Execute_expression(std::string const& str) {
using iterator_type = std::string::const_iterator;
using calculator = client::calculator<iterator_type>;
namespace ast = client::ast;
calculator const calc; // Our grammar
ast::eval const eval; // Evaluates the program
ast::program program;
auto f(std::begin(str)), l(std::end(str));
bool r = phrase_parse(f, l, calc, client::qi::space, program);
if (r && f == l) {
std::cout << "Result: " << quoted(str, '\'') << " -> " << eval(program)
<< std::endl;
return eval(program);
} else {
std::cout << "Failed at: " << quoted(std::string(f, l), '\'') << "\n";
}
return 0;
};
};
int main(){
Expression_handler exp;
exp.Execute_expression(R"("abc" == "abc")");
exp.Execute_expression(R"("abc" != "abc")");
exp.Execute_expression(R"("abc" == "cba")");
exp.Execute_expression(R"("abc" != "cba")");
}
Prints
Result: '"abc" == "abc"' -> 1
Result: '"abc" != "abc"' -> 0
Result: '"abc" == "cba"' -> 0
Result: '"abc" != "cba"' -> 1

Compiling error when insert pair into set [duplicate]

This question already has answers here:
problems with c++ set container
(2 answers)
Closed 6 years ago.
I can't understand why g++ returns error like this:
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_pair.h: In function 鈥榖ool std::operator<(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&) [with _T1 = int, _T2 = stop]鈥
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_function.h:227: instantiated from 鈥榖ool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = std::pair<int, stop>]鈥
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_tree.h:921: instantiated from 鈥榮td::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique(const _Val&) [with _Key = std::pair<int, stop>, _Val = std::pair<int, stop>, _KeyOfValue = std::_Identity<std::pair<int, stop> >, _Compare = std::less<std::pair<int, stop> >, _Alloc = std::allocator<std::pair<int, stop> >]鈥
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_set.h:321: instantiated from 鈥榮td::pair<typename std::_Rb_tree<_Key, _Key, std::_Identity<_Key>, _Compare, typename _Alloc::rebind<_Key>::other>::const_iterator, bool> std::set<_Key, _Compare, _Alloc>::insert(const _Key&) [with _Key = std::pair<int, stop>, _Compare = std::less<std::pair<int, stop> >, _Alloc = std::allocator<std::pair<int, stop> >]鈥
newGraph.cpp:48: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.1.2/../../../../include/c++/4.1.2/bits/stl_pair.h:104: error: no match for 鈥榦perator<鈥in 鈥榑_x->std::pair<int, stop>::second < __y->std::pair<int, stop>::second鈥
Here is my code:
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <set>
#include <utility> // for pair
#include <algorithm>
#include <iterator>
const int max_weight = INT_MAX;
struct stop {
std::string name_stop;
int id_stop;
bool operator !=(const stop &rhs) const
{
return ((id_stop != rhs.id_stop) || (name_stop != rhs.name_stop));
}
};
struct neighbor {
stop target;
int weight;
neighbor(stop arg_target, int arg_weight) : target(arg_target), weight(arg_weight) { }
};
std::list<stop> dijkstraComputeAndGetShortestPaths(stop src,
stop dst,
std::vector< std::vector<neighbor> > &adj_list,
std::vector<int> &min_distance,
std::vector<stop> &previous)
{
stop fake_stop;
fake_stop.id_stop = INT_MAX;
fake_stop.name_stop = "Null";
std::list<stop> path;
int n = adj_list.size();
min_distance.clear();
min_distance.resize(n, max_weight);
min_distance[src.id_stop] = 0;
previous.clear();
previous.resize(n, fake_stop);
std::set< std::pair< int, stop > > vertex_queue;
vertex_queue.insert(std::make_pair(min_distance[src.id_stop], src));
while (!vertex_queue.empty())
{
int dist = vertex_queue.begin()->first;
stop u = vertex_queue.begin()->second;
vertex_queue.erase(vertex_queue.begin());
// Visit each edge exiting u
const std::vector<neighbor> &neighbors = adj_list[u.id_stop];
for(std::vector<neighbor>::const_iterator neighbor_iter = neighbors.begin();
neighbor_iter != neighbors.end();
neighbor_iter++)
{
stop v = neighbor_iter->target;
int weight = neighbor_iter->weight;
int distance_through_u = dist + weight;
if (distance_through_u < min_distance[v.id_stop]) {
vertex_queue.erase(std::make_pair(min_distance[v.id_stop], v));
min_distance[v.id_stop] = distance_through_u;
previous[v.id_stop] = u;
vertex_queue.insert(std::make_pair(min_distance[v.id_stop], v));
}
}
if(u.id_stop == dst.id_stop)
{
std::cout << "Find : ";
for ( ; dst != fake_stop; dst = previous[dst.id_stop])
{
path.push_front(dst);
}
return path;
}
}
}
int main()
{
std::vector< std::vector<neighbor> > adj_list(9);
stop stop_s;
stop_s.id_stop = 1001;
stop_s.name_stop = "A";
stop stop_x;
stop_x.id_stop = 1002;
stop_x.name_stop = "B";
adj_list[stop_s.id_stop].push_back(neighbor(stop_x, 5));
stop_s.id_stop = 1003;
stop_s.name_stop = "C";
adj_list[stop_x.id_stop].push_back(neighbor(stop_s, 15));
stop_x.id_stop = 1004;
stop_x.name_stop = "D";
adj_list[stop_s.id_stop].push_back(neighbor(stop_x, 20));
stop_s.id_stop = 1001;
stop_s.name_stop = "A";
std::vector<int> min_distance;
std::vector<stop> previous;
std::list<stop> path = dijkstraComputeAndGetShortestPaths(stop_s, stop_x, adj_list, min_distance, previous);
std::cout << "Distance from 1001 to 1004: " << min_distance[stop_x.id_stop] << std::endl;
//std::cout << "Path : ";
#if 0
for (int index = 0; index < path.size(); index++)
{
auto path_front = path.begin();
std::advance(path_front, index);
std::cout << path_front->id_stop << " ";
}
std::cout << std::endl;
#endif
return 0;
}
std::set require you to specify an operator < for the type it holds or you can supply your own comparison functor as a template parameter. Since stop does not have an operator < the operator < from std::pair is not compileable since it relies on using the operator < of the types it holds.. You either need to supply your own comparison functor or define an operator < for stop.

Using boost::function and boost::bind

I have the following code trying to pass non-static member functions as a replacement idea to old c code where it requires function pointer. It is not compiling. Could you help? Something must be obvious and I am new to this. Thanks in advance. -- Jinping
#include <iostream>
#include <boost/function.hpp>
#include <boost/function_equal.hpp>
#include <boost/bind.hpp>
using namespace boost;
using namespace std;
double addTest( boost::function<double (double)> f, double a, double x )
{
double a1 = f(a);
double a2= a1+x;
return a2;
}
double squareIt (double x) {
return x*x;
}
class X {
public:
X(double x0, double x1){ x=x0+x1; }
double plusIt(double t) { return x+t; }
private:
double x;
};
int main (int argc, char** argv)
{
boost::function<double (double)> f;
f = &squareIt;
double result = addTest(f, 10, 5); //OK
cout << "result = " << result << endl;
X newx(10, 15);
//f=boost::bind(&X::plusIt, &newx); // does not complie
double res2 = addTest(boost::bind(&X::plusIt, &newx), 10, 5); // does not compile
cout << "result2 = " << res2 << endl;
return 0;
}
// compile error:
g++ -Wall -g -O0 -I/meth_mount/utility_sys/boost_1_42_0/ -I/usr/include -I/meth_mount/utility_sys/gsl-1.15/ -I/home/ayuan/work/ird_lib/core_lib/alib/intrface/build/alib/clib/linux -DUNIX -DSET_ENVIRONMENT -DOPTION_RESET -c ./../src/BindTest.cpp
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp: In static member function ‘static R boost::detail::function::function_obj_invoker1::invoke(boost::detail::function::function_buffer&, T0) [with FunctionObj = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’:
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:913: instantiated from ‘void boost::function1::assign_to(Functor) [with Functor = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:722: instantiated from ‘boost::function1::function1(Functor, typename boost::enable_if_c::value>::value, int>::type) [with Functor = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:1064: instantiated from ‘boost::function::function(Functor, typename boost::enable_if_c::value>::value, int>::type) [with Functor = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
./../src/BindTest.cpp:46: instantiated from here
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:132: error: cannot convert ‘double ()(double)’ to ‘double’ in return
/meth_mount/utility_sys/boost_1_42_0/boost/bind/mem_fn.hpp: In member function ‘R& boost::_mfi::dm::operator()(T) const [with R = double ()(double), T = X]’:
/meth_mount/utility_sys/boost_1_42_0/boost/bind/bind.hpp:243: instantiated from ‘R boost::_bi::list1::operator()(boost::_bi::type, F&, A&, long int) [with R = double (&)(double), F = boost::_mfi::dm, A = boost::_bi::list1, A1 = boost::_bi::value]’
/meth_mount/utility_sys/boost_1_42_0/boost/bind/bind_template.hpp:32: instantiated from ‘typename boost::_bi::result_traits::type boost::_bi::bind_t::operator()(A1&) [with A1 = double, R = double (&)(double), F = boost::_mfi::dm, L = boost::_bi::list1 >]’
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:132: instantiated from ‘static R boost::detail::function::function_obj_invoker1::invoke(boost::detail::function::function_buffer&, T0) [with FunctionObj = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:913: instantiated from ‘void boost::function1::assign_to(Functor) [with Functor = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:722: instantiated from ‘boost::function1::function1(Functor, typename boost::enable_if_c::value>::value, int>::type) [with Functor = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
/meth_mount/utility_sys/boost_1_42_0/boost/function/function_template.hpp:1064: instantiated from ‘boost::function::function(Functor, typename boost::enable_if_c::value>::value, int>::type) [with Functor = boost::_bi::bind_t, boost::_bi::list1 > >, R = double, T0 = double]’
./../src/BindTest.cpp:46: instantiated from here
/meth_mount/utility_sys/boost_1_42_0/boost/bind/mem_fn.hpp:342: error: invalid use of non-static member function
make: *** [../bin/BindTest.o] Error 1
You are missing _1 which is required because X::plusIt is an unary function (not counting this). The correct code is
double res2 = addTest(boost::bind(&X::plusIt, &newx, _1), 10, 5);
See also Using bind with pointers to members.

boost::qi::parse seems to cause compilation errors

I'm trying to write a parser using Boost::Spirit, and I have the parser written and compiling. The problem is, when I try to compile the parsing function, the compiler throws out a bunch of template errors. Here's the Qi grammar:
template<typename Iterator>
struct etf_parser : qi::grammar<Iterator, std::map<std::string, etfnode>(), ascii::space_type> {
etf_parser() : etf_parser::base_type(start) {
using qi::int_;
using qi::lit;
using qi::double_;
using qi::bool_;
using qi::lexeme;
using ascii::char_;
quoted_string %= lexeme['"' >> +(char_ - '"') >> '"'];
dataVal %= (quoted_string | double_ | int_ | bool_ | listObj | pairObj | mapObj);
pairObj %= ('<' >> dataVal >> ',' >> dataVal >> '>');
listObj %= '{' >> dataVal % ',' >> '}';
mapKey %= +qi::char_("a-zA-Z_-0-9.");
mapPair %= mapKey >> lit('=') >> dataVal;
mapObj %= '(' >> mapPair % ',' >> ')';
start %= mapPair >> ';';
}
qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
// Data value parsers
qi::rule<Iterator, etfnode(), ascii::space_type> dataVal;
qi::rule<Iterator, std::vector<etfnode>(), ascii::space_type> listObj;
qi::rule<Iterator, std::pair<etfnode, etfnode>(), ascii::space_type> pairObj;
qi::rule<Iterator, std::map<std::string, etfnode>(), ascii::space_type> mapObj;
qi::rule<Iterator, std::pair<std::string, etfnode>(), ascii::space_type> mapPair;
qi::rule<Iterator, std::string(), ascii::space_type> mapKey;
qi::rule<Iterator, std::map<std::string, etfnode>(), ascii::space_type> start;
};
And here's the parsing function. When I comment out the qi::parse call, the code compiles fine:
ETFDocument::ETFDocument(std::string content) {
etf_parser<std::string::const_iterator> parser;
std::map<std::string, rwnode> results;
std::string::const_iterator begin = content.begin();
std::string::const_iterator end = content.end();
bool result = qi::parse(begin, end, parser, results);
if(result) printf("Parsing succeeded\n"); else printf("Parsing failed\n");
m_root = etfnode(results);
}
The compiler spits out the following error when I try to compile:
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /usr/include/boost/spirit/home/qi.hpp:20,
from /usr/include/boost/spirit/include/qi.hpp:16,
from libmcg/etf.cpp:8:
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp: In instantiation of ‘bool boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Context = boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >; Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; T1 = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/usr/include/boost/spirit/home/qi/reference.hpp:43:71: required from ‘bool boost::spirit::qi::reference<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type>]’
/usr/include/boost/spirit/home/qi/parse.hpp:86:82: required from ‘bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >; Expr = etf_parser<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> > >; Attr = std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >]’
libmcg/etf.cpp:113:53: required from here
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:303:17: error: no match for call to ‘(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::fusion::vector0<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>}) (__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >, 0l>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::unused_type&)’
In file included from /usr/include/boost/function/detail/maybe_include.hpp:33:0,
from /usr/include/boost/function/detail/function_iterate.hpp:14,
from /usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,
from /usr/include/boost/function.hpp:64,
from /usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:16,
from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:20,
from /usr/include/boost/spirit/include/qi.hpp:16,
from libmcg/etf.cpp:8:
/usr/include/boost/function/function_template.hpp:1021:7: note: candidate is:
/usr/include/boost/function/function_template.hpp:754:17: note: boost::function4<R, T1, T2, T3, T4>::result_type boost::function4<R, T1, T2, T3, T4>::operator()(T0, T1, T2, T3) const [with R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::map<std::basic_string<char>, boost::recursive_wrapper<ETFDocument::etfnode> >&, boost::fusion::nil>, boost::fusion::vector0<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; boost::function4<R, T1, T2, T3, T4>::result_type = bool]
/usr/include/boost/function/function_template.hpp:754:17: note: no known conversion for argument 4 from ‘const boost::spirit::unused_type’ to ‘const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&’
As far as I can tell, it's looking for a Skipper, but getting boost::spirit::unused_type instead. I'm not sure why this would happen, since I specified a Skipper in my parser definition. I'm using boost v1.49.0 on gcc 4.7.1.
EDIT: Here's the definition for etfnode. There's a typedef at the beginning of the cpp file (containing the other code fragments) that aliases "etfnode" to "rwnode".
enum DataType {
DT_INT,
DT_STRING,
DT_FLOAT,
DT_BOOL,
DT_LIST,
DT_PAIR,
DT_MAP
};
struct etfnode;
typedef boost::recursive_wrapper<etfnode> rwnode;
typedef boost::variant<
int,
std::string,
double,
bool,
std::vector<rwnode>,
std::pair<rwnode, rwnode>,
std::map<std::string, rwnode> > etfvalue;
struct etfnode {
DataType type;
etfvalue value;
etfnode(const std::string& s);
etfnode(const int i);
etfnode(const double d);
etfnode(const bool b);
etfnode(const std::vector<rwnode>& n);
etfnode(const std::pair<rwnode, rwnode>& p);
etfnode(const std::map<std::string, rwnode>& p);
etfnode();
};
And a test string:
foo = 6;
bar = <"bar", 16.5>;
baz = {
(
foobar = "foo",
bar = 12
),
"foobar"
};
I think the most important culprit was the fact that you were using qi::parse instead of qi::phrase_parse, while your grammar explicitely uses a skipper.
I also rewrote the defintion of the etfvalue recursive variant. I'm not sure whether your version should have worked, but at least now, you can just use etfnode in all places where you'd expect to. It looks more consistent to me this way.
Here's code that compiles fine for me. It parses the sample input (see main()) with the following output:
Parsing succeeded
Unparsed remaining: ';'
If you actually wanted to accept the trailing ;, fix the main rule to be more like
start = *(mapPair >> ';'); // or *(mapPair >> (';'|qi::eoi))
Good luck!
//add streaming operators for etfnode and etfvalue if you want to debug this:
//#define BOOST_SPIRIT_DEBUG
#include <map>
#include <string>
#include <boost/variant/recursive_wrapper.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted.hpp>
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
enum DataType {
DT_INT,
DT_STRING,
DT_FLOAT,
DT_BOOL,
DT_LIST,
DT_PAIR,
DT_MAP
};
struct etfnode;
typedef boost::variant<
int,
std::string,
double,
bool,
boost::recursive_wrapper<std::vector<etfnode> >,
boost::recursive_wrapper<std::pair<etfnode, etfnode> >,
boost::recursive_wrapper<std::map<std::string, etfnode> >
> etfvalue;
struct etfnode {
DataType type;
etfvalue value;
etfnode(const std::string& s) { value = s; type = DT_STRING; }
etfnode(const int i) { value = i; type = DT_INT; }
etfnode(const double d) { value = d; type = DT_FLOAT; }
etfnode(const bool b) { value = b; type = DT_BOOL; }
etfnode(const std::vector<etfnode>& n) { value = n; type = DT_LIST; }
etfnode(const std::pair<etfnode, etfnode>& p) { value = p; type = DT_PAIR; }
etfnode(const std::map<std::string, etfnode>& p) { value = p; type = DT_MAP; }
etfnode() { }
};
template<typename Iterator>
struct etf_parser : qi::grammar<Iterator, std::map<std::string, etfnode>(), ascii::space_type> {
etf_parser() : etf_parser::base_type(start) {
using qi::int_;
using qi::lit;
using qi::double_;
using qi::bool_;
using qi::lexeme;
using ascii::char_;
quoted_string = lexeme['"' >> +(char_ - '"') >> '"'];
dataVal = (quoted_string | double_ | int_ | bool_
| listObj | pairObj
| mapObj
);
listObj = '{' >> dataVal % ',' >> '}';
pairObj = lit('<') >> dataVal >> ',' >> dataVal >> '>';
mapKey = +qi::char_("a-zA-Z_-0-9.");
mapPair = mapKey >> lit('=') >> dataVal;
mapObj = '(' >> mapPair % ',' >> ')';
start = mapPair % ';';
BOOST_SPIRIT_DEBUG_NODE(quoted_string);
BOOST_SPIRIT_DEBUG_NODE(dataVal);
BOOST_SPIRIT_DEBUG_NODE(listObj);
//BOOST_SPIRIT_DEBUG_NODE(pairObj);
BOOST_SPIRIT_DEBUG_NODE(mapObj);
BOOST_SPIRIT_DEBUG_NODE(mapKey);
BOOST_SPIRIT_DEBUG_NODE(mapPair);
BOOST_SPIRIT_DEBUG_NODE(start);
}
qi::rule<Iterator, std::string(), ascii::space_type> quoted_string;
// Data value parsers
qi::rule<Iterator, etfnode(), ascii::space_type> dataVal;
qi::rule<Iterator, std::vector<etfnode>(), ascii::space_type> listObj;
qi::rule<Iterator, std::pair<etfnode, etfnode>(), ascii::space_type> pairObj;
qi::rule<Iterator, std::map<std::string, etfnode>(), ascii::space_type> mapObj;
qi::rule<Iterator, std::pair<std::string, etfnode>(), ascii::space_type> mapPair;
qi::rule<Iterator, std::string(), ascii::space_type> mapKey;
qi::rule<Iterator, std::map<std::string, etfnode>(), ascii::space_type> start;
};
int main()
{
etf_parser<std::string::const_iterator> parser;
std::map<std::string, etfnode> results;
std::string content = "foo = 6;\n"
"bar = <\"bar\", 16.5>;\n"
"baz = {\n"
" (\n"
" foobar = \"foo\",\n"
" bar = 12\n"
" ),\n"
" \"foobar\"\n"
"};";
std::string::const_iterator begin = content.begin();
std::string::const_iterator end = content.end();
bool result = qi::phrase_parse(begin, end, parser, ascii::space, results);
if(result) printf("Parsing succeeded\n"); else printf("Parsing failed\n");
if (begin!=end)
std::cout << "Unparsed remaining: '" << std::string(begin,end) << "'\n";
//m_root = etfnode(results);
}

Compiling simple boost spirit grammar

I'm having trouble getting a small boost::spirit grammar to compile. It's a small part of a larger grammar that I'm having trouble with and I'm trying to test smaller parts to find my problem.
Basicly what this grammar should do is parse a double value which has any number of leading/trailing spaces. However when I try to compile I get a whole list of problems which I don't understand. Any help would be welcome!
The code:
grammar.h
#ifndef GRAMMAR_H
#define GRAMMAR_H
#include <boost/spirit/include/qi.hpp>
template <typename Iterator>
struct point_double_grammar : boost::spirit::qi::grammar<Iterator, double()>
{
/**
* Constructor used to create the grammar.
* #param is_point boolean indicating if the point is used as decimal.
* #author Luc Kleeven
**/
point_double_grammar() : point_double_grammar::base_type(d)
{
d = *boost::spirit::qi::lit(' ') >> boost::spirit::qi::double_ >> *boost::spirit::qi::lit(' ');
}
boost::spirit::qi::rule<Iterator, double()> d;
};
#endif // GRAMMAR_H
main.cpp
#include "grammar.h"
int main(int argc, char *argv[])
{
point_double_grammar<std::string::iterator> point_grammar();
bool result = false;
double d = 0.0;
std::string p1 = "575040.3400";
std::string p2 = "117380.1200";
std::string p3 = "-001.22916765";
std::string p4 = "063.39171738";
std::string p5 = "2.5";
std::string::iterator it;
std::string::iterator last;
it = p1.begin();
last = p1.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it ==
last);
if(result)
{
std::cout << p1 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p2.begin();
last = p2.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it ==
last);
if(result)
{
std::cout << p2 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p3.begin();
last = p3.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it == last);
if(result)
{
std::cout << p3 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p4.begin();
last = p4.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it == last);
if(result)
{
std::cout << p4 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
it = p5.begin();
last = p5.end();
result = (boost::spirit::qi::parse(it, last, point_grammar, d) && it == last);
if(result)
{
std::cout << p5 << " == " << d << std::endl;
}
else
{
std::cout << "Parsing failed!" << std::endl;
}
return EXIT_SUCCESS;
}
When I try to compile I get the following errors:
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/detail/parse_auto.hpp:14:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/auto.hpp:16,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi.hpp:15,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/include/qi.hpp:16,
from ../test/grammar.h:4,
from ../test/main.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp: In function 'bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]':
../test/main.cpp:20:63: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:83:9: error: no matching function for call to 'assertion_failed(mpl_::failed************ (boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]::error_invalid_expression::************)(point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > > (*)()))'
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:83:9: note: candidate is:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/mpl/assert.hpp:79:48: note: template<bool C> int mpl_::assertion_failed(typename mpl_::assert<C>::type)
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/expr.hpp:6:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/expr.hpp:120,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/core.hpp:17,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/proto.hpp:12,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/support/meta_compiler.hpp:19,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/meta_compiler.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/action/action.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/action.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi.hpp:14,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/include/qi.hpp:16,
from ../test/grammar.h:4,
from ../test/main.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/preprocessed/expr.hpp: At global scope:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/preprocessed/expr.hpp: In instantiation of 'boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()>, 0l>':
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/utility/enable_if.hpp:59:10: instantiated from 'boost::disable_if<boost::proto::is_expr<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()>, 0l>, void>, void>'
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/support/meta_compiler.hpp:212:16: instantiated from 'boost::spirit::result_of::compile<boost::spirit::qi::domain, point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), boost::spirit::unused_type, void>'
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:86:82: instantiated from 'bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]'
../test/main.cpp:20:63: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/proto/detail/preprocessed/expr.hpp:50:49: error: field 'boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()>, 0l>::child0' invalidly declared function type
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/detail/parse_auto.hpp:14:0,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/auto.hpp:16,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi.hpp:15,
from c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/include/qi.hpp:16,
from ../test/grammar.h:4,
from ../test/main.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp: In function 'bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), Attr = double]':
../test/main.cpp:20:63: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.6.1/../../../../include/boost/spirit/home/qi/parse.hpp:86:82: error: request for member 'parse' in 'boost::spirit::compile [with Domain = boost::spirit::qi::domain, Expr = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >(), typename boost::spirit::result_of::compile<Domain, Expr, boost::spirit::unused_type>::type = point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > > (&)()]((* & expr))', which is of non-class type 'point_double_grammar<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> > >()'
Note that I'm compiling using boost 1.48.0 and mingw 4.6.1 on a windows 7 machine.
Change this line:
point_double_grammar<std::string::iterator> point_grammar();
To:
point_double_grammar<std::string::iterator> point_grammar;
You've declared a function taking no arguments that returns a grammar. Instead, you want to instantiate the grammar.
Sharth has already answered your question, you should accept that answer of course.
I wanted to share a few other things, you might find helpful.
as I mentioned: format your code (code is for humans)
Try using a loop instead of duplicating your code. You weren't parsing a list of doubles. You were parsing a single double, 5 times
Avoid C-isms (declare and initialize at the top?)
Look at Qi Skippers: you were manually 'ignoring' whitespace. Qi has Skippers for that purpose (see qi::phrase_parse in below sample)
Consider using Boost Karma for output generation. At least use <iomanip> to control the output format (see std::setprecision below)
Here is the full example
#include <boost/spirit/include/qi.hpp>
#include <iomanip>
namespace qi = boost::spirit::qi;
template <typename Iterator, typename Skipper>
struct point_double_grammar : qi::grammar<Iterator, double(), Skipper>
{
point_double_grammar() : point_double_grammar::base_type(d)
{
d = qi::double_;
}
qi::rule<Iterator, double(), Skipper> d;
};
static const char *const testcases[] = {
"575040.3400",
"117380.1200",
"-001.22916765",
"063.39171738",
"2.5",
NULL
};
int main()
{
typedef std::string::const_iterator It;
point_double_grammar<It, qi::space_type> point_grammar;
for(const char* const* it=testcases; *it; ++it)
{
const std::string input(*it);
It it = input.begin(), last = input.end();
double d = 0.0;
bool result = (qi::phrase_parse(it, last, point_grammar, qi::space, d) && it ==
last);
if(result)
std::cout << input << " == "
<< std::setprecision(10) << d << std::endl;
else
std::cerr << "Parsing failed!" << std::endl;
}
}
With C++11 you'd even write:
for (const std::string input : {
"575040.3400", "117380.1200", "-001.22916765", "063.39171738", "2.5" })
{
auto it = input.begin(), last = input.end();
etc. For the record, the output is:
575040.3400 == 575040.34
117380.1200 == 117380.12
-001.22916765 == -1.22916765
063.39171738 == 63.39171738
2.5 == 2.5
Without std::setprecision(10) the output would be, e.g. 575040.3400 == 575040 for the first line. Consider using Boost Karma for output generation.