I have been writing a grammar in C++ using Spirit Qi from Boost library. As a novice in the language, it was a tough to get used to the syntax and quirks of the library but now I kind of understand how it works.
I am having an error when using qi::lexeme. My actual grammar is quite big, so I made a small code snippet where the same problem is present. The following code compiles without errors:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <set>
#include <iostream>
#include <string>
#include <complex>
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
typedef boost::tuple<char, char> range;
}
namespace client
{
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, range(), ascii::space_type>
{
employee_parser() : employee_parser::base_type(start)
{
using qi::lit;
using qi::lexeme;
using ascii::char_;
range_rule =
char_("a-z") >> lit("-") >> char_("a-z")
| char_("A-Z") >> lit("-") >> char_("A-Z")
| char_("0-9") >> lit("-") >> char_("0-9")
;
start = range_rule;
}
qi::rule<Iterator, range(), ascii::space_type> range_rule;
qi::rule<Iterator, range(), ascii::space_type> start;
};
}
int main()
{
typedef std::string::const_iterator iterator_type;
typedef client::employee_parser<iterator_type> employee_parser;
employee_parser g;
return 0;
}
Now, if I replace the line start = range_rule; and use start = lexeme[range_rule]; instead, the compilation fails.
As I read from the docs, lexeme[a] should preserve the subject parser's attributes, so I can't understand why it fails. The output error is huge and pretty cryptic so I don't have any clues:
In file included from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi.hpp:21,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/include/qi.hpp:16,
from cpp/tests/test2.cpp:2:
/home/martin/vscode_cpp_projects/boost_1_68_0/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<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attribute = boost::tuples::tuple<char, char>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, char>(); 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’:
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/reference.hpp:43:72: 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::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >; Attribute = boost::tuples::tuple<char, char>; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/directive/lexeme.hpp:66:64: required from ‘typename boost::disable_if<boost::spirit::qi::detail::is_unused_skipper<Skipper>, bool>::type boost::spirit::qi::lexeme_directive<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Attribute = boost::tuples::tuple<char, char>; Subject = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >; typename boost::disable_if<boost::spirit::qi::detail::is_unused_skipper<Skipper>, bool>::type = bool]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54: required from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Parser = boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >; Auto = mpl_::bool_<false>; mpl_::false_ = mpl_::bool_<false>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:24: required from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::operator()(Iterator&, const Iterator&, Context&, const Skipper&) const [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >; Context = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >; Parser
= boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >; Auto = mpl_::bool_<false>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:138:22: required from ‘static R boost::detail::function::function_obj_invoker4<FunctionObj, R, T0, T1, T2, T3>::invoke(boost::detail::function::function_buffer&, T0, T1, T2, T3) [with FunctionObj = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:936:38: [ skipping 2 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:1074:16: required from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), int>::type = int]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:1127:5: required from ‘typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::lexeme_directive<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> > >,
mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_c<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&)>&]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:183:19: required from ‘static void boost::spirit::qi::rule<Iterator,
T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, char>(); 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::true_ = mpl_::bool_<true>]’
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:221:32: required from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3,
T4>& boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::lexeme>, 0>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::tuples::tuple<char, char>(); 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> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
cpp/tests/test2.cpp:40:19: required from ‘client::employee_parser<Iterator>::employee_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >]’
cpp/tests/test2.cpp:56:21: required from here
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:304:17: error: no match for call to ‘(const function_type {aka const boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&, 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::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::tuples::tuple<char, char>(), 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> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>::context_type&, const boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >&)’
if (f(first, last, context, skipper))
^~
In file included from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/detail/maybe_include.hpp:43:0,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/detail/function_iterate.hpp:14,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/preprocessor/iteration/detail/iter/forward1.hpp:67,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/function.hpp:70,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal/rule.hpp:16,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi/nonterminal.hpp:14,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/home/qi.hpp:21,
from /home/martin/vscode_cpp_projects/boost_1_68_0/boost/spirit/include/qi.hpp:16,
from cpp/tests/test2.cpp:2:
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:763:17: note: candidate: 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::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::tuples::tuple<char, char>&, boost::fusion::nil_>, boost::fusion::vector<> >&; 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]
result_type operator()(BOOST_FUNCTION_PARMS) const
^~~~~~~~
/home/martin/vscode_cpp_projects/boost_1_68_0/boost/function/function_template.hpp:763:17: note: no known conversion for argument 4 from ‘const boost::spirit::qi::detail::unused_skipper<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> > >’ to ‘const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::ascii> >&’
As I read from the docs, lexeme[a] should preserve the subject parser's attributes, so I can't understand why it fails.
Yes it preserves the attributes. It does NOT preserve the skipper (for obvious reasons), and your range_rule declares one. The compiler messages contain this info:
BOOST_STATIC_ASSERT_MSG((is_same<skipper_type, unused_type>::value ||
!is_same<Skipper, unused_type>::value),
"The rule was instantiated with a skipper type but you have not pass any. "
"Did you use `parse` instead of `phrase_parse`?");
So, drop the skipper from the range_rule. Ironically, just dropping it will implicitly make it behave like a lexeme so you wouldn't need the lexeme[] around it anyways.
See also Boost spirit skipper issues
In short:
can't call rule that requires a skipper without one
okay to call an implicit lexeme rule from a parser with a skipper context
I usually group my rules to indicate as much, and preface them with a comment, like:
private:
qi::rule<Iterator, range(), ascii::space_type> start;
// lexmes
qi::rule<Iterator, range()> range_rule;
But I also usually encapsulate the skipper unless it really makes sense (?!) for the caller to change the skipper.
See also similar tasks:
Parsing comma-separated list of ranges and numbers with semantic actions
method for expand a-z to abc...xyz form
Suggested Fixes
Live On Coliru
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <set>
#include <iostream>
#include <string>
#include <complex>
namespace client
{
namespace qi = boost::spirit::qi;
typedef boost::tuple<char, char> range;
}
namespace client
{
template <typename Iterator>
struct employee_parser : qi::grammar<Iterator, range()>
{
employee_parser() : employee_parser::base_type(start)
{
using qi::lit;
using qi::lexeme;
using qi::ascii::char_;
range_rule =
char_("a-z") >> lit("-") >> char_("a-z")
| char_("A-Z") >> lit("-") >> char_("A-Z")
| char_("0-9") >> lit("-") >> char_("0-9")
;
start = qi::skip(qi::ascii::space) [ range_rule ];
}
private:
qi::rule<Iterator, range()> start;
// lexmes
qi::rule<Iterator, range()> range_rule;
};
}
int main()
{
typedef std::string::const_iterator iterator_type;
typedef client::employee_parser<iterator_type> employee_parser;
employee_parser g;
std::string const input("a-k");
client::range r;
return parse(begin(input), end(input), g, r)
? 0
: 1;
}
Related
I have a C++ code that uses boost 1.60 and compiles fine. It is a simple math parser.
Code is here with CI that shows that it compiles fine with gcc
Updating to boost 1.79 leads to the following compilation error error: no matching function for call to 'boost::variant'
I have isolated the problem with this code, and spotted the constructor that creates the error (with comments)
Any advise would be helpful!
#include <cstdint>
#include <iostream>
#include <boost/variant.hpp>
#include <boost/version.hpp>
#include <boost/foreach.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/spirit/include/qi.hpp>
#define INCLUDE_FROM_BOOST_1_79
#ifdef INCLUDE_FROM_BOOST_1_79
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/fusion.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/phoenix/object.hpp>
#include <boost/phoenix/stl.hpp>
#else
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#endif
namespace fusion = boost::fusion;
namespace phoenix = boost::phoenix;
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
using qi::double_;
using qi::eol;
using qi::lit;
using qi::lexeme;
using qi::on_error;
using qi::fail;
using ascii::char_;
using ascii::alpha;
using ascii::alnum;
using ascii::string;
using namespace qi::labels;
using phoenix::at_c;
using phoenix::push_back;
using phoenix::construct;
using phoenix::val;
namespace maneuvering
{
typedef ascii::blank_type SpaceType;
struct Nil
{
};
struct FunctionCall;
typedef std::string Identifier;
typedef boost::variant<
Nil
, double
, Identifier
, boost::recursive_wrapper<FunctionCall>
>
Atom;
struct Expr;
typedef boost::variant<
Nil
, boost::recursive_wrapper<Expr>
, boost::recursive_wrapper<Atom>
>
Base;
struct Factor
{
Base base;
std::vector<Base> exponents;
};
struct OperatorAndFactor
{
std::string operator_;
Factor factor;
};
struct Term
{
Factor first;
std::vector<OperatorAndFactor> rest;
};
struct OperatorAndTerm
{
std::string operator_;
Term term;
};
struct Expr
{
Term first;
std::vector<OperatorAndTerm> rest;
};
struct FunctionCall
{
Identifier function;
Expr expr;
};
}
BOOST_FUSION_ADAPT_STRUCT(
maneuvering::Factor,
(maneuvering::Base, base)
(std::vector<maneuvering::Base>, exponents)
)
BOOST_FUSION_ADAPT_STRUCT(
maneuvering::OperatorAndTerm,
(std::string, operator_)
(maneuvering::Term, term)
)
BOOST_FUSION_ADAPT_STRUCT(
maneuvering::OperatorAndFactor,
(std::string, operator_)
(maneuvering::Factor, factor)
)
BOOST_FUSION_ADAPT_STRUCT(
maneuvering::Term,
(maneuvering::Factor, first)
(std::vector<maneuvering::OperatorAndFactor>, rest)
)
BOOST_FUSION_ADAPT_STRUCT(
maneuvering::Expr,
(maneuvering::Term, first)
(std::vector<maneuvering::OperatorAndTerm>, rest)
)
BOOST_FUSION_ADAPT_STRUCT(
maneuvering::FunctionCall,
(maneuvering::Identifier, function)
(maneuvering::Expr, expr)
)
namespace maneuvering
{
struct ArithmeticGrammar : qi::grammar<std::string::const_iterator, Expr(), SpaceType>
{
// Begin of the section that create boost compilation problem
ArithmeticGrammar() : ArithmeticGrammar::base_type(expr)
{
using boost::spirit::ascii::alnum;
using boost::spirit::ascii::alpha;
expr = term >> *(operator_and_term);
add_operators = qi::char_("+") | qi::char_("-");
mul_operators = qi::char_("*") | qi::char_("/");
operator_and_term = add_operators >> term;
operator_and_factor = mul_operators >> factor;
term = factor >> *(operator_and_factor);
factor = base >> *( '^' >> exponent);
base = ('(' >> expr >> ')') | atom; // Specific problematic line
exponent = base;
atom = function_call | identifier | double_;
function_call = identifier >> '(' >> expr >> ')';
identifier = alpha >> *(alnum | qi::char_('_'));
}
// End of the section that create boost compilation problem
qi::rule<std::string::const_iterator, Expr(), SpaceType> expr;
qi::rule<std::string::const_iterator, std::string(), SpaceType> add_operators;
qi::rule<std::string::const_iterator, std::string(), SpaceType> mul_operators;
qi::rule<std::string::const_iterator, OperatorAndTerm(), SpaceType> operator_and_term;
qi::rule<std::string::const_iterator, OperatorAndFactor(), SpaceType> operator_and_factor;
qi::rule<std::string::const_iterator, Term(), SpaceType> term;
qi::rule<std::string::const_iterator, Factor(), SpaceType> factor;
qi::rule<std::string::const_iterator, Base(), SpaceType> base;
qi::rule<std::string::const_iterator, Base(), SpaceType> exponent;
qi::rule<std::string::const_iterator, Atom(), SpaceType> atom;
qi::rule<std::string::const_iterator, FunctionCall(), SpaceType> function_call;
qi::rule<std::string::const_iterator, Identifier(), SpaceType> identifier;
};
}
int main(int argc, char* agrv[])
{
std::cout << "Using Boost "
<< BOOST_VERSION / 100000 << "." // major version
<< BOOST_VERSION / 100 % 1000 << "." // minor version
<< BOOST_VERSION % 100 // patch level
<< std::endl;
}
Error is below
In file included from /usr/local/include/boost/spirit/home/qi/auxiliary/attr.hpp:18,
from /usr/local/include/boost/spirit/home/qi/auxiliary.hpp:19,
from /usr/local/include/boost/spirit/home/qi.hpp:16,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:8:
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp: In instantiation of 'static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, T, Enable>::call(const T_&, Attribute&, mpl_::false_) [with T_ = boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >; Attribute = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >; T = boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >; Enable = void; mpl_::false_ = mpl_::bool_<false>]':
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:171:17: required from 'static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, T, Enable>::call(const T&, Attribute&) [with Attribute = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >; T = boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >; Enable = void]'
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:370:63: required from 'void boost::spirit::traits::detail::assign_to(const T&, Attribute&, mpl_::false_) [with T = boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >; Attribute = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >; mpl_::false_ = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:393:26: required from 'void boost::spirit::traits::assign_to(const T&, Attribute&) [with T = boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >; Attribute = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >]'
/usr/local/include/boost/spirit/home/qi/detail/alternative_function.hpp:109:34: required from 'bool boost::spirit::qi::detail::alternative_function<Iterator, Context, Skipper, Attribute>::call_variant(const Component&, mpl_::false_) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> > >; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >; Attribute = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >; mpl_::false_ = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/detail/alternative_function.hpp:132:32: required from 'bool boost::spirit::qi::detail::alternative_function<Iterator, Context, Skipper, Attribute>::call_optional_or_variant(const Component&, mpl_::false_) const [with Component = boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> > >; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; Context = boost::spirit::context<boost::fusion::cons<boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >; Attribute = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >; mpl_::false_ = mpl_::bool_<false>]'
/usr/local/include/boost/spirit/home/qi/detail/alternative_function.hpp:139:44: [ skipping 12 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/local/include/boost/function/function_template.hpp:720:22: required from 'boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, maneuvering::Expr(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil_> > > >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> > >, boost::fusion::nil_> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
/usr/local/include/boost/function/function_template.hpp:1094:16: required from 'boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, maneuvering::Expr(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil_> > > >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> > >, boost::fusion::nil_> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]'
/usr/local/include/boost/function/function_template.hpp:1147:5: required from 'typename boost::enable_if_<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::alternative<boost::fusion::cons<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, maneuvering::Expr(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::cons<boost::spirit::qi::literal_char<boost::spirit::char_encoding::standard, true, false>, boost::fusion::nil_> > > >, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> > >, boost::fusion::nil_> > >, mpl_::bool_<false> >; R = bool; T0 = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >&)>&]'
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:191:19: required from 'static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const char&>, 0>, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, maneuvering::Expr(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const char&>, 0> >, 2>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> >&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::true_ = mpl_::bool_<true>]'
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:229:32: required from 'boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::operator=(const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::bitwise_or, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::shift_right, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const char&>, 0>, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, maneuvering::Expr(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2>&, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<const char&>, 0> >, 2>&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >, boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >(), boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0> >&>, 2>; Iterator = __gnu_cxx::__normal_iterator<const char*, std::__cxx11::basic_string<char> >; T1 = boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >(); T2 = boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::blank, boost::spirit::char_encoding::ascii> >, 0>; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]'
main.cpp:171:47: required from here
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: no matching function for call to 'boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >::variant(const boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >&)'
153 | attr = static_cast<Attribute>(val);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/boost/variant.hpp:17,
from main.cpp:3:
/usr/local/include/boost/variant/variant.hpp:1770:5: note: candidate: 'boost::variant<T0, TN>::variant(boost::variant<T0, TN>&&) [with T0_ = maneuvering::Nil; TN = {boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > >}]'
1770 | variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
| ^~~~~~~
/usr/local/include/boost/variant/variant.hpp:1770:23: note: no known conversion for argument 1 from 'const boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >' to 'boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&&'
1770 | variant(variant&& operand) BOOST_NOEXCEPT_IF(variant_move_noexcept_constructible::type::value)
| ~~~~~~~~~~^~~~~~~
/usr/local/include/boost/variant/variant.hpp:1759:5: note: candidate: 'boost::variant<T0, TN>::variant(const boost::variant<T0, TN>&) [with T0_ = maneuvering::Nil; TN = {boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > >}]'
1759 | variant(const variant& operand)
| ^~~~~~~
/usr/local/include/boost/variant/variant.hpp:1759:28: note: no known conversion for argument 1 from 'const boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> >' to 'const boost::variant<maneuvering::Nil, boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > > >&'
1759 | variant(const variant& operand)
| ~~~~~~~~~~~~~~~^~~~~~~
/usr/local/include/boost/variant/variant.hpp:1375:5: note: candidate: 'boost::variant<T0, TN>::variant() [with T0_ = maneuvering::Nil; TN = {boost::recursive_wrapper<maneuvering::Expr>, boost::recursive_wrapper<boost::variant<maneuvering::Nil, double, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::recursive_wrapper<maneuvering::FunctionCall> > >}]'
1375 | variant()
| ^~~~~~~
/usr/local/include/boost/variant/variant.hpp:1375:5: note: candidate expects 0 arguments, 1 provided
This example can be tested here: it is useful to see the whole error message that is cryptic for me and that is useful to debug...
It was broken by Boost.Variant change, filed the issue https://github.com/boostorg/variant/issues/100.
The offending thing is boost::recursive_wrapper<Atom>, if you replace it with Atom -- it will compile. https://wandbox.org/permlink/HtUO3QjUI7cO2ySj
This code is not my actual code, but just illustrates the issue. I have a rule that matches 0 or more digits, and an action that is supposed to count them and return that count as the synthesized attribute.
The attribute of *qi::ascii::digit should be a std::vector of the matched digits. So, I wrote the action so that it simply calls .size() and assigns the result to the synthesized attribute. To call .size(), I use boost.phoenix to bind a lambda that calls .size().
#include <boost/phoenix/bind/bind_function_object.hpp>
#include <boost/phoenix/core.hpp>
#include <boost/phoenix/operator.hpp>
#include <boost/spirit/include/qi.hpp>
#include <cstdint>
#include <iostream>
#include <string>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
using It = std::string::iterator;
struct Parser : qi::grammar<std::string::iterator, size_t()> {
Parser() : Parser::base_type(r) {
auto count = [](auto&& v) { return v.size(); };
r %= (*qi::ascii::digit)[qi::_val = phx::bind(count, qi::_1)];
}
qi::rule<It, size_t()> r;
};
int main() {
using namespace std;
std::string s = "123";
int c;
Parser p;
qi::parse(s.begin(), s.end(), p, c);
std::cout << c << '\n';
}
But it doesn't work. I expect this code to compile and print 3. Instead, I get a very long compile error. The error is roughly what I would expect if the action were simply qi::_val = qi::_1, which perplexes me.
In file included from /usr/local/include/boost/type_traits/is_convertible.hpp:20,
from /usr/local/include/boost/type_traits/is_empty.hpp:12,
from /usr/local/include/boost/mpl/empty_base.hpp:23,
from /usr/local/include/boost/fusion/sequence/intrinsic/at.hpp:15,
from /usr/local/include/boost/phoenix/core/expression.hpp:11,
from /usr/local/include/boost/phoenix/bind/bind_function_object.hpp:17,
from spirit2.cpp:1:
/usr/local/include/boost/spirit/home/qi/parse.hpp: In instantiation of ‘bool boost::spirit::qi::parse(Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = int; Attr = Parser]’:
/usr/local/include/boost/spirit/home/qi/parse.hpp:100:25: required from ‘bool boost::spirit::qi::parse(const Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = int; Attr = Parser]’
spirit2.cpp:27:39: required from here
/usr/local/include/boost/spirit/home/qi/parse.hpp:85:9: error: static assertion failed: error_invalid_expression
BOOST_SPIRIT_ASSERT_MATCH(qi::domain, Expr);
^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/local/include/boost/spirit/home/qi/detail/parse_auto.hpp:14,
from /usr/local/include/boost/spirit/home/qi/auto.hpp:16,
from /usr/local/include/boost/spirit/home/qi.hpp:15,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from spirit2.cpp:4:
/usr/local/include/boost/spirit/home/qi/parse.hpp:88:42: error: request for member ‘parse’ in ‘boost::spirit::compile<boost::spirit::qi::domain, int>((* & expr))’, which is of non-class type ‘boost::spirit::result_of::compile<boost::spirit::qi::domain, boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<int>, 0>, boost::spirit::unused_type, void>::type’ {aka ‘int’}
return compile<qi::domain>(expr).parse(first, last, context, unused, attr);
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
In file included from /usr/local/include/boost/spirit/home/qi/auxiliary/attr.hpp:18,
from /usr/local/include/boost/spirit/home/qi/auxiliary.hpp:19,
from /usr/local/include/boost/spirit/home/qi.hpp:16,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from spirit2.cpp:4:
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp: In instantiation of ‘static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, T, Enable>::call(const T_&, Attribute&, mpl_::false_) [with T_ = std::vector<char, std::allocator<char> >; Attribute = long unsigned int; T = std::vector<char, std::allocator<char> >; Enable = void; mpl_::false_ = mpl_::bool_<false>]’:
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:171:17: required from ‘static void boost::spirit::traits::assign_to_attribute_from_value<Attribute, T, Enable>::call(const T&, Attribute&) [with Attribute = long unsigned int; T = std::vector<char, std::allocator<char> >; Enable = void]’
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:370:63: required from ‘void boost::spirit::traits::detail::assign_to(const T&, Attribute&, mpl_::false_) [with T = std::vector<char, std::allocator<char> >; Attribute = long unsigned int; mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:393:26: required from ‘void boost::spirit::traits::assign_to(const T&, Attribute&) [with T = std::vector<char, std::allocator<char> >; Attribute = long unsigned int]’
/usr/local/include/boost/spirit/home/qi/detail/attributes.hpp:27:30: required from ‘static void boost::spirit::qi::default_transform_attribute<Exposed, Transformed>::post(Exposed&, const Transformed&) [with Exposed = long unsigned int; Transformed = std::vector<char, std::allocator<char> >]’
/usr/local/include/boost/spirit/home/qi/action/action.hpp:71:36: required from ‘bool boost::spirit::qi::action<Subject, Action>::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<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >; Skipper = boost::spirit::unused_type; Attribute = long unsigned int; Subject = boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >; Action = boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:73:54: [ skipping 3 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/local/include/boost/function/function_template.hpp:720:7: required from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::action<boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> > >, mpl_::bool_<true> >; R = bool; T0 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::unused_type&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1068:16: required from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::action<boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> > >, mpl_::bool_<true> >; R = bool; T0 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::unused_type&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1121:5: required from ‘typename boost::enable_if_<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::action<boost::spirit::qi::kleene<boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> > >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> > >, mpl_::bool_<true> >; R = bool; T0 = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&; T3 = const boost::spirit::unused_type&; typename boost::enable_if_<(! boost::is_integral<Functor>::value), boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__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<long unsigned int&, boost::fusion::nil_>, boost::fusion::vector<> >&, const boost::spirit::unused_type&)>&]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:185:19: required from ‘static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<true>; Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> >, 0>&>, 1>&, const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >&>, 2>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; T1 = long unsigned int(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type; mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:249:31: required from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::operator%=(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, Expr&&) [with Expr = const boost::proto::exprns_::expr<boost::proto::tagns_::tag::subscript, boost::proto::argsns_::list2<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::dereference, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::tag::char_code<boost::spirit::tag::digit, boost::spirit::char_encoding::ascii> >, 0>&>, 1>&, const boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::assign, boost::proto::argsns_::list2<boost::phoenix::actor<boost::spirit::attribute<0> >, boost::phoenix::actor<boost::proto::exprns_::basic_expr<boost::phoenix::detail::tag::function_eval, boost::proto::argsns_::list2<boost::proto::exprns_::basic_expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<Parser::Parser()::<lambda(auto:1&&)> >, 0>, boost::phoenix::actor<boost::spirit::argument<0> > >, 2> > >, 2> >&>, 2>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; T1 = long unsigned int(); T2 = boost::spirit::unused_type; T3 = boost::spirit::unused_type; T4 = boost::spirit::unused_type]’
spirit2.cpp:16:69: required from here
/usr/local/include/boost/spirit/home/qi/detail/assign_to.hpp:153:20: error: invalid static_cast from type ‘const std::vector<char, std::allocator<char> >’ to type ‘long unsigned int’
attr = static_cast<Attribute>(val);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
The solution is to drop %:
r = (*qi::ascii::digit)[qi::_val = phx::bind(count, qi::_1)];
The important error message is in the last line: error: invalid static_cast from type ‘const std::vector<char, std::allocator<char> >’ to type ‘long unsigned int’
For why it produces vector<char> see here.
There is use of semantic action and:
r %= p and r = p are equivalent if there are no semantic actions
associated with p.
Read more about it here.
The doqtor did an excellent job of introducing the relevant concepts. I'd just like to show some simplification if you have a recent compiler (which it looks like you do):
phx::function count { [](auto&& v) { return v.size(); } };
r = (*digit)[_val = count(_1)];
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
using It = std::string::const_iterator;
struct Parser : qi::grammar<It, size_t()> {
Parser() : Parser::base_type(r) {
using namespace qi;
phx::function count { [](auto&& v) { return v.size(); } };
r = (*digit)[_val = count(_1)];
}
private:
qi::rule<It, size_t()> r;
};
int main() {
std::string const s = "123";
int c;
Parser p;
if (qi::parse(s.begin(), s.end(), p, c)) {
std::cout << "Number of digits: " << c << "\n";
}
}
Prints
Number of digits: 3
I am trying to build a parser using boost::spirit that, besides other stuff, should be able to parse pairs of integers such as "(3,4)".
My code is working but I also want to accept pairs that contain spaces, i.e. "( 4 , 6 )". When trying to add the space_type skipper as shown in the boost spirit tutorial the following code fails to compile. I can not see the grave mistake I am making (I suspected using the wrong namespace but it seems to be the correct one).
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/include/std_pair.hpp>
using namespace std;
using namespace boost::spirit::qi;
using position = std::pair<int, int>;
template<typename Iterator>
struct position_grammar : grammar<Iterator, position(), boost::spirit::ascii::space_type> {
position_grammar() : position_grammar::base_type(start) {
start = lit("(") >> int_ >> lit(",") >> int_ >> lit(")");
}
rule<Iterator, position(),boost::spirit::ascii::space_type> start;
};
int main() {
std::string s = "(1,2)";
position_grammar<std::string::iterator> grammar;
position p;
bool r = parse(s.begin(), s.end(), grammar,p);
cout << "parsing: " << r << " position: " << p.first << ", " << p.second << "\n";
return 0;
}
Compiler output:
In file included from /usr/include/boost/spirit/home/qi/nonterminal.hpp:14:0,
from /usr/include/boost/spirit/home/qi.hpp:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from /home/pansen/proggs/foo/src/foo/model/routing_parser_test.cpp:2:
/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::pair<int, int>&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::pair<int, int>; Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; T1 = std::pair<int, int>(); 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:72: required from ‘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<std::pair<int, int>&, boost::fusion::nil_>, boost::spirit::locals<> >; Skipper = boost::spirit::unused_type; Attribute = std::pair<int, int>; Subject = const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >, std::pair<int, int>(), 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<char*, std::__cxx11::basic_string<char> >; Expr = position_grammar<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> > >; Attr = std::pair<int, int>]’
/usr/include/boost/spirit/home/qi/parse.hpp:98:25: required from ‘bool boost::spirit::qi::parse(const Iterator&, Iterator, const Expr&, Attr&) [with Iterator = __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >; Expr = position_grammar<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> > >; Attr = std::pair<int, int>]’
/home/pansen/proggs/foo/src/foo/model/routing_parser_test.cpp:23:46: required from here
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:304:17: error: no match for call to ‘(const function_type {aka const boost::function<bool(__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<std::pair<int, int>&, 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<char*, std::__cxx11::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >, std::pair<int, int>(), 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&)’
if (f(first, last, context, skipper))
^
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:21,
from /usr/include/boost/spirit/include/qi.hpp:16,
from /home/pansen/proggs/foo/src/foo/model/routing_parser_test.cpp:2:
/usr/include/boost/function/function_template.hpp:767:17: note: candidate: 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<char*, std::__cxx11::basic_string<char> >&; T1 = const __gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >&; T2 = boost::spirit::context<boost::fusion::cons<std::pair<int, int>&, 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]
result_type operator()(BOOST_FUNCTION_PARMS) const
^
/usr/include/boost/function/function_template.hpp:767: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> >&’
The error points to if (f(first, last, context, skipper)) which looks like the error here (see answer by sehe). But I already correctly specify the attribute (at least I think so).
If you wish to use a skipper, you must pass an instance of it, by calling phrase_parse instead of parse:
bool r = phrase_parse(s.begin(), s.end(), grammar, qi::space, p);
Alternatively, you can hide the details about the skipper by declaring it in a enclosing skipper-less rule with skip(qi::space) [ real_start_rule_with_skipper ]
See also: Boost spirit skipper issues
Notes:
do not use using namespace - especially not both std and boost::spirit::qi at the same time. You can always use using namespace qi; locally
no need to wrap every literal in lit(). Here's the rule simplified:
position_rule = '(' >> qi::int_ >> ',' >> qi::int_ >> ')';
DEMO
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/std_pair.hpp>
namespace qi = boost::spirit::qi;
using position = std::pair<int, int>;
template <typename Iterator> struct position_grammar : qi::grammar<Iterator, position()> {
position_grammar() : position_grammar::base_type(start) {
position_rule = '(' >> qi::int_ >> ',' >> qi::int_ >> ')';
start = qi::skip(boost::spirit::ascii::space) [ position_rule ];
}
qi::rule<Iterator, position()> start;
qi::rule<Iterator, position(), boost::spirit::ascii::space_type> position_rule;
};
int main() {
std::string s = " ( 1\t,\r\n2 )";
position_grammar<std::string::iterator> grammar;
position p;
bool r = parse(s.begin(), s.end(), grammar, p);
std::cout << "parsing: " << r << " position: " << p.first << ", " << p.second << "\n";
}
Prints
parsing: 1 position: 1, 2
Problem description
I have a trivial struct, adapted for boost::fusion:
struct Node
{
std::string text;
};
BOOST_FUSION_ADAPT_STRUCT(Node, (std::string, text))
I have a grammar with a set of rules:
boost::spirit::qi::rule<Iterator, Node()> node_line;
boost::spirit::qi::rule<Iterator, Node()> node;
And there is one rule that blows up in my face:
node_line %= " * " >> node;
I would expect this to be valid, since the attribute of the literal is unused, and node_line and node have the same attribute type. Instead the compiler complains:
/usr/include/boost/spirit/home/support/container.hpp:262:13: error: no matching function for call to ‘std::basic_string<char>::insert(std::basic_string<char>::iterator, const Node&)’
I.e. the compiler tries to append a struct Node onto a std::string. I am utterly confused as to why it would try to do that. Any thoughts?
Full code
#include <boost/config/warning_disable.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/qi.hpp>
struct Node
{
std::string text;
};
BOOST_FUSION_ADAPT_STRUCT(Node, (std::string, text))
template <typename Iterator>
struct My_parser : boost::spirit::qi::grammar<Iterator, Node()>
{
My_parser()
: My_parser::base_type(node_line)
{
name %= +boost::spirit::ascii::char_;
node %= name;
node_line %= " * " >> node;
// node_line %= node;
}
boost::spirit::qi::rule<Iterator, std::string()> name;
boost::spirit::qi::rule<Iterator, Node()> node_line;
boost::spirit::qi::rule<Iterator, Node()> node;
};
int main()
{
const std::string input(" * Some text");
Node parsed;
My_parser<std::string::const_iterator> my_parser;
bool r = parse(input.begin(), input.end(), my_parser, parsed);
if(r)
std::cout << "Match: " << parsed.text << std::endl;
else
std::cout << "No match" << std::endl;
return 0;
}
Full error message
In file included from /usr/include/boost/spirit/home/support/string_traits.hpp:16:0,
from /usr/include/boost/spirit/home/support/nonterminal/expand_arg.hpp:20,
from /usr/include/boost/spirit/home/support/context.hpp:15,
from /usr/include/boost/spirit/home/qi/domain.hpp:18,
from /usr/include/boost/spirit/home/qi/meta_compiler.hpp:15,
from /usr/include/boost/spirit/home/qi/action/action.hpp:14,
from /usr/include/boost/spirit/home/qi/action.hpp:14,
from /usr/include/boost/spirit/home/qi.hpp:14,
from /usr/include/boost/spirit/include/qi.hpp:16,
from tt.cc:3:
/usr/include/boost/spirit/home/support/container.hpp: In static member function ‘static bool boost::spirit::traits::push_back_container<Container, T, Enable>::call(Container&, const T&) [with Container = std::basic_string<char>, T = Node, Enable = void]’:
/usr/include/boost/spirit/home/support/container.hpp:324:62: instantiated from ‘bool boost::spirit::traits::push_back(Container&, const T&) [with Container = std::basic_string<char>, T = Node]’
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:168:13: instantiated from ‘static void boost::spirit::traits::assign_to_container_from_value<Attribute, T, Enable>::call(const T_&, Attribute&, mpl_::false_, mpl_::false_) [with T_ = Node, Attribute = std::basic_string<char>, T = Node, Enable = void, mpl_::false_ = mpl_::bool_<false>]’
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:203:13: instantiated from ‘static void boost::spirit::traits::assign_to_container_from_value<Attribute, T, Enable>::call(const T&, Attribute&) [with Attribute = std::basic_string<char>, T = Node, Enable = void]’
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:243:13: instantiated from ‘void boost::spirit::traits::detail::assign_to(const T&, Attribute&, mpl_::true_, mpl_::true_) [with T = Node, Attribute = std::basic_string<char>, mpl_::true_ = mpl_::bool_<true>]’
/usr/include/boost/spirit/home/qi/detail/assign_to.hpp:257:9: instantiated from ‘void boost::spirit::traits::assign_to(const T&, Attribute&) [with T = Node, Attribute = std::basic_string<char>]’
/usr/include/boost/spirit/home/qi/detail/attributes.hpp:26:13: [ skipping 12 instantiation contexts ]
/usr/include/boost/function/function_template.hpp:913:60: instantiated from ‘void boost::function4<R, T1, T2, T3, T4>::assign_to(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_string<const char (&)[5], true>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Node(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::nil> > >, mpl_::bool_<true> >, 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<Node&, boost::fusion::nil>, boost::fusion::vector0<> >&, T3 = const boost::spirit::unused_type&]’
/usr/include/boost/function/function_template.hpp:722:7: instantiated from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_string<const char (&)[5], true>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Node(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::nil> > >, mpl_::bool_<true> >, 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<Node&, boost::fusion::nil>, boost::fusion::vector0<> >&, T3 = const boost::spirit::unused_type&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1064:16: instantiated from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_string<const char (&)[5], true>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Node(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::nil> > >, mpl_::bool_<true> >, 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<Node&, boost::fusion::nil>, boost::fusion::vector0<> >&, T3 = const boost::spirit::unused_type&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/include/boost/function/function_template.hpp:1105:5: instantiated from ‘typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::sequence<boost::fusion::cons<boost::spirit::qi::literal_string<const char (&)[5], true>, boost::fusion::cons<boost::spirit::qi::reference<const boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Node(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type> >, boost::fusion::nil> > >, mpl_::bool_<true> >, 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<Node&, boost::fusion::nil>, boost::fusion::vector0<> >&, T3 = const boost::spirit::unused_type&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type = 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<Node&, boost::fusion::nil>, boost::fusion::vector0<> >&, const boost::spirit::unused_type&)>&]’
/usr/include/boost/spirit/home/qi/nonterminal/rule.hpp:214:13: instantiated from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>& boost::spirit::qi::operator%=(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&) [with Expr = boost::proto::exprns_::expr<boost::proto::tag::shift_right, boost::proto::argsns_::list2<boost::proto::exprns_::expr<boost::proto::tag::terminal, boost::proto::argsns_::term<const char (&)[5]>, 0l>, boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Node(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>&>, 2l>, Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, T1 = Node(), T2 = boost::spirit::unused_type, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >, Node(), boost::spirit::unused_type, boost::spirit::unused_type, boost::spirit::unused_type>]’
tt.cc:21:5: instantiated from ‘My_parser<Iterator>::My_parser() [with Iterator = __gnu_cxx::__normal_iterator<const char*, std::basic_string<char> >]’
tt.cc:34:42: instantiated from here
/usr/include/boost/spirit/home/support/container.hpp:262:13: error: no matching function for call to ‘std::basic_string<char>::insert(std::basic_string<char>::iterator, const Node&)’
/usr/include/boost/spirit/home/support/container.hpp:262:13: note: candidates are:
/usr/include/c++/4.6/bits/basic_string.h:1174:7: note: void std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::iterator, std::basic_string<_CharT, _Traits, _Alloc>::size_type, _CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, typename _Alloc::rebind<_CharT>::other::pointer = char*, std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
/usr/include/c++/4.6/bits/basic_string.h:1174:7: note: candidate expects 3 arguments, 2 provided
/usr/include/c++/4.6/bits/basic_string.h:1190:9: note: template<class _InputIterator> void std::basic_string::insert(std::basic_string<_CharT, _Traits, _Alloc>::iterator, _InputIterator, _InputIterator) [with _InputIterator = _InputIterator, _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, typename _Alloc::rebind<_CharT>::other::pointer = char*]
/usr/include/c++/4.6/bits/basic_string.h:1220:7: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::size_type, const std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>, std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
/usr/include/c++/4.6/bits/basic_string.h:1220:7: note: no known conversion for argument 1 from ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ to ‘long unsigned int’
/usr/include/c++/4.6/bits/basic_string.h:1242:7: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::size_type, const std::basic_string<_CharT, _Traits, _Alloc>&, std::basic_string<_CharT, _Traits, _Alloc>::size_type, std::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>, std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
/usr/include/c++/4.6/bits/basic_string.h:1242:7: note: candidate expects 4 arguments, 2 provided
/usr/include/c++/4.6/bits/basic_string.tcc:361:6: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::size_type, const _CharT*, std::basic_string<_CharT, _Traits, _Alloc>::size_type) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
/usr/include/c++/4.6/bits/basic_string.tcc:361:6: note: candidate expects 3 arguments, 2 provided
/usr/include/c++/4.6/bits/basic_string.h:1283:7: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::size_type, const _CharT*) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>, std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
/usr/include/c++/4.6/bits/basic_string.h:1283:7: note: no known conversion for argument 1 from ‘std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}’ to ‘long unsigned int’
/usr/include/c++/4.6/bits/basic_string.h:1306:7: note: std::basic_string<_CharT, _Traits, _Alloc>& std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::size_type, std::basic_string<_CharT, _Traits, _Alloc>::size_type, _CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc> = std::basic_string<char>, std::basic_string<_CharT, _Traits, _Alloc>::size_type = long unsigned int]
/usr/include/c++/4.6/bits/basic_string.h:1306:7: note: candidate expects 3 arguments, 2 provided
/usr/include/c++/4.6/bits/basic_string.h:1323:7: note: std::basic_string<_CharT, _Traits, _Alloc>::iterator std::basic_string<_CharT, _Traits, _Alloc>::insert(std::basic_string<_CharT, _Traits, _Alloc>::iterator, _CharT) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>, std::basic_string<_CharT, _Traits, _Alloc>::iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, typename _Alloc::rebind<_CharT>::other::pointer = char*]
/usr/include/c++/4.6/bits/basic_string.h:1323:7: note: no known conversion for argument 2 from ‘const Node’ to ‘char’
Compiler/boost version
This is ubuntu 12.04
gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
boost 1.46.
Having said that, I managed to reproduce my question on ubuntu 14.04 (gcc 4.8.2, boost 1.54)
This reminds me a lot of this infamous limitation:
Spirit Qi attribute propagation issue with single-member struct
However, I cannot make it click, and the usual workarounds don't seem to apply. You might report it on the [spirit-general] mailing list.
In the mean time, here's a phoenix workaround:
node_line = " * " >> node [qi::_val=qi::_1];
See it Live On Coliru
This question already has an answer here:
Spirit Qi attribute propagation issue with single-member struct
(1 answer)
Closed 8 years ago.
#include <iostream>
#include <vector>
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/io.hpp>
namespace qi = boost::spirit::qi;
struct VectorWrapper
{
std::vector<std::string> data;
};
BOOST_FUSION_ADAPT_STRUCT(
VectorWrapper,
(std::vector<std::string>, data)
)
int main ()
{
std::string input("aa aa aa");
std::string::iterator strbegin = input.begin();
qi::rule<std::string::iterator, VectorWrapper(), qi::space_type > testRule =
+(qi::string("aa"));
VectorWrapper result;
bool ok = qi::phrase_parse(
strbegin,
input.end(),
testRule,
qi::space,
result);
if (ok && strbegin == input.end()) {
std::cout << result.data.size();
for (int i = 0; i < result.data.size(); ++i) {
std::cout << result.data[i] << " ";
}
} else {
std::cout << "fail" << std::endl;
std::cout << std::string(strbegin, input.end()) << std::endl;
}
}
I need help to find out problem in this code. Compiler complains about type in VectorWrapper struct but shouldn't BOOST_FUSION_ADAPT_STRUCT add it?
After adding dummy field (from this answer)I am getting the same error:
struct VectorWrapper
{
std::vector<std::string> data;
qi::unused_type dummy;
};
BOOST_FUSION_ADAPT_STRUCT(
VectorWrapper,
(std::vector<std::string>, data)
(qi::unused_type, dummy)
)
The error message:
In file included from /usr/local/include/boost/spirit/home/support/string_traits.hpp:16:0,
from /usr/local/include/boost/spirit/home/support/nonterminal/expand_arg.hpp:20,
from /usr/local/include/boost/spirit/home/support/context.hpp:18,
from /usr/local/include/boost/spirit/home/qi/domain.hpp:18,
from /usr/local/include/boost/spirit/home/qi/meta_compiler.hpp:15,
from /usr/local/include/boost/spirit/home/qi/action/action.hpp:14,
from /usr/local/include/boost/spirit/home/qi/action.hpp:14,
from /usr/local/include/boost/spirit/home/qi.hpp:14,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:4:
/usr/local/include/boost/spirit/home/support/container.hpp: In instantiation of ‘boost::spirit::traits::container_value<VectorWrapper, void>’:
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:296:66: instantiated from ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::dispatch_attribute(const Component&, mpl_::true_) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>, mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:331:61: instantiated from ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::operator()(const Component&) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:63:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse_container(F) const [with F = boost::spirit::qi::detail::pass_container<boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, VectorWrapper, mpl_::bool_<false> >, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:85:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Attribute = VectorWrapper, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Parser = boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, Auto = mpl_::bool_<false>, mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:67: [ skipping 3 instantiation contexts ]
/usr/local/include/boost/function/function_template.hpp:722:7: instantiated from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1069:16: instantiated from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1124:5: instantiated from ‘typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&)>&]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:13: instantiated from ‘static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>, Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, VectorWrapper(), 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> >, 0l> >, mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:191:13: instantiated from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::rule(const Expr&, const string&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, std::string = std::basic_string<char>]’
main.cpp:27:27: instantiated from here
/usr/local/include/boost/spirit/home/support/container.hpp:116:12: error: no type named ‘value_type’ in ‘struct VectorWrapper’
In file included from /usr/local/include/boost/spirit/home/qi/operator/kleene.hpp:20:0,
from /usr/local/include/boost/spirit/home/qi/directive/repeat.hpp:18,
from /usr/local/include/boost/spirit/home/qi/directive.hpp:23,
from /usr/local/include/boost/spirit/home/qi.hpp:19,
from /usr/local/include/boost/spirit/include/qi.hpp:16,
from main.cpp:4:
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp: In member function ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::dispatch_attribute(const Component&, mpl_::true_) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>, mpl_::true_ = mpl_::bool_<true>]’:
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:331:61: instantiated from ‘bool boost::spirit::qi::detail::pass_container<F, Attr, Sequence>::operator()(const Component&) const [with Component = boost::spirit::qi::literal_string<const char (&)[3], false>, F = boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, Attr = VectorWrapper, Sequence = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:63:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse_container(F) const [with F = boost::spirit::qi::detail::pass_container<boost::spirit::qi::detail::fail_function<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> > >, VectorWrapper, mpl_::bool_<false> >, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/operator/plus.hpp:85:13: instantiated from ‘bool boost::spirit::qi::plus<Subject>::parse(Iterator&, const Iterator&, Context&, const Skipper&, Attribute&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Attribute = VectorWrapper, Subject = boost::spirit::qi::literal_string<const char (&)[3], false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:43:54: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::call(Iterator&, const Iterator&, Context&, const Skipper&, mpl_::false_) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Parser = boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, Auto = mpl_::bool_<false>, mpl_::false_ = mpl_::bool_<false>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/detail/parser_binder.hpp:53:67: instantiated from ‘bool boost::spirit::qi::detail::parser_binder<Parser, Auto>::operator()(Iterator&, const Iterator&, Context&, const Skipper&) const [with Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, Skipper = boost::spirit::qi::char_class<boost::spirit::tag::char_code<boost::spirit::tag::space, boost::spirit::char_encoding::standard> >, Context = boost::spirit::context<boost::fusion::cons<VectorWrapper&, boost::fusion::nil>, boost::fusion::vector0<> >, Parser = boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, Auto = mpl_::bool_<false>]’
/usr/local/include/boost/function/function_template.hpp:132:42: [ skipping 2 instantiation contexts ]
/usr/local/include/boost/function/function_template.hpp:722:7: instantiated from ‘boost::function4<R, T1, T2, T3, T4>::function4(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1069:16: instantiated from ‘boost::function<R(T0, T1, T2, T3)>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, int>::type = int]’
/usr/local/include/boost/function/function_template.hpp:1124:5: instantiated from ‘typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type boost::function<R(T0, T1, T2, T3)>::operator=(Functor) [with Functor = boost::spirit::qi::detail::parser_binder<boost::spirit::qi::plus<boost::spirit::qi::literal_string<const char (&)[3], false> >, mpl_::bool_<false> >, R = bool, T0 = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T1 = const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, T2 = boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&, typename boost::enable_if_c<boost::type_traits::ice_not<boost::is_integral<Functor>::value>::value, boost::function<R(T0, T1, T2, T3)>&>::type = boost::function<bool(__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, const __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >&, boost::spirit::context<boost::fusion::cons<VectorWrapper&, 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::standard> >&)>&]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:182:13: instantiated from ‘static void boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::define(boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>&, const Expr&, mpl_::true_) [with Auto = mpl_::bool_<false>, Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, boost::spirit::qi::rule<Iterator, T1, T2, T3, T4> = boost::spirit::qi::rule<__gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, VectorWrapper(), 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> >, 0l> >, mpl_::true_ = mpl_::bool_<true>]’
/usr/local/include/boost/spirit/home/qi/nonterminal/rule.hpp:191:13: instantiated from ‘boost::spirit::qi::rule<Iterator, T1, T2, T3, T4>::rule(const Expr&, const string&) [with Expr = boost::proto::exprns_::expr<boost::proto::tagns_::tag::unary_plus, boost::proto::argsns_::list1<const boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal, boost::proto::argsns_::term<boost::spirit::terminal_ex<boost::spirit::tag::char_code<boost::spirit::tag::string, boost::spirit::char_encoding::standard>, boost::fusion::vector1<const char (&)[3]> > >, 0l>&>, 1l>, Iterator = __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >, T1 = VectorWrapper(), 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> >, 0l>, T3 = boost::spirit::unused_type, T4 = boost::spirit::unused_type, std::string = std::basic_string<char>]’
main.cpp:27:27: instantiated from here
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:296:66: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_value<VectorWrapper, void>’
/usr/local/include/boost/spirit/home/qi/detail/pass_container.hpp:309:15: error: no type named ‘type’ in ‘struct boost::spirit::traits::container_value<VectorWrapper, void>’
make: *** [all] Error 1
You need to emit an unused type in your rule:
qi::rule<std::string::iterator, VectorWrapper(), qi::space_type > testRule =
+(qi::string("aa")) >> qi::attr(false);
The linked answer should be enough. Since you report trouble still: here's something that works on my compilers:
qi::rule<std::string::iterator, VectorWrapper(), qi::space_type > testRule =
qi::eps >> +(qi::string("aa"));
See it Live On Coliru