I'm struggling to get to grips with boost qi parser semantic actions, using boost::bind and class members as follows:
#include <boost/spirit/include/qi.hpp>
#include <boost/bind/bind.hpp>
#include <string>
#include <iostream>
namespace qi = boost::spirit::qi;
class Parser
{
public:
Parser() {}
~Parser() {}
void GotComment(std::wstring const& s)
{
std::wcout << s << std::endl;
}
};
template <typename IteratorT, typename SkipperT>
struct comment_grammar
: qi::grammar<IteratorT, SkipperT, std::wstring()>
{
comment_grammar(Parser& parser)
: comment_grammar::base_type(rule, "Comment")
, _parser(parser)
{
using namespace qi;
using qi::standard_wide::print;
using boost::placeholders::_1;
rule %= L'#' >> lexeme[*print] [boost::bind(&Parser::GotComment, &_parser, _1)];
}
qi::rule<IteratorT, SkipperT, std::wstring()> rule;
Parser& _parser;
};
int main()
{
using namespace qi;
using qi::standard_wide::blank_type;
using qi::standard_wide::blank;
using IteratorT = std::wstring::const_iterator;
std::wstring result;
std::wstring source(L"# A comment");
IteratorT iter = source.cbegin();
Parser parser;
comment_grammar<IteratorT, blank_type> cg(parser);
bool b = qi::phrase_parse<IteratorT>(iter, source.cend(), cg, blank, result);
if (b)
std::wcout << L"Succeeded: " << result << std::endl;
else
std::wcout << L"Parsing failed" << std::endl;
return 0;
}
When compiled with Visual C++ 2019 and boost 1.76.0, it generates a 460 line error message starting:
boost\bind\bind.hpp(303,1): error C2664: 'R boost::_mfi::mf1<R,Parser,std::wstring>::operator ()(T &,A1) const': cannot convert argument 1 from 'const T' to 'T &'
with
[
R=void,
T=Parser,
A1=std::wstring
]
and
[
T=Parser *
]
and
[
T=Parser
]
This is caused by the semantic action for the rule definition in comment_grammar. If I comment that out, all is well and the matching text is returned in result, but I really want Parser::GotComment to process it. Can anyone enlighten me?