This has been plaguing me for hours, and I do not understand how to make it work. I simply want to do something each time a rule is used, in this example increment a counter. If I do not explicitly specify the rule but use it in the call to boost::spirit::karma::generate, it works. But when I try to put everything into a rule, it will not compile, and I do not get any insight from the lengthy error message.
#include <iostream>
#include <string>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
int main()
{
using boost::spirit::karma::eps;
using boost::spirit::karma::int_;
using boost::spirit::karma::lit;
using boost::spirit::karma::eol;
using boost::phoenix::val;
using boost::phoenix::ref;
using boost::spirit::karma::generate;
using boost::spirit::karma::rule;
typedef std::back_insert_iterator<std::string> OutputIteratorType;
std::string s;
std::back_insert_iterator<std::string> sink(s);
int lineNum = 0;
generate(sink, eps[ref(lineNum) += 10] << lit("Line number ") << lit(lineNum) << lit(": ") << int_ << eol, 123);
generate(sink, eps[ref(lineNum) += 10] << lit("Line number ") << lit(lineNum) << lit(": ") << int_ << eol, 123);
// Will not compile
//rule<OutputIteratorType, int()> testRule = eps[ref(lineNum) += 10] << lit("Line number ") << lit(lineNum) << lit(": ") << int_ << eol;
//generate(sink, testRule, 123);
//generate(sink, testRule, 123);
std::cout << s;
return 0;
}
(Above you can see the boost::spirit version which is most elegant, but using a lambda function or a member function all results in the same, the "direct method" works, the "rule method" doesn't.)
Unfortunately I also cannot find any documentation or examples or other resources that cover this, I'd be very thankful for references too.
That is a problem with boost::phoenix V2 (don't ask which ;-)) So, using V3 will work.
Additionally one has to give the attribute to the int generator and reference the lineNum when printing it.
#include <iostream>
#include <string>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
int main() {
using boost::spirit::karma::eps;
using boost::spirit::karma::int_;
using boost::spirit::karma::lit;
using boost::spirit::karma::eol;
using boost::spirit::karma::_1;
using boost::spirit::karma::_val;
using boost::phoenix::val;
using boost::phoenix::ref;
using boost::spirit::karma::generate;
using boost::spirit::karma::rule;
typedef std::back_insert_iterator<std::string> OutputIteratorType;
std::string s;
std::back_insert_iterator<std::string> sink(s);
int lineNum = 0;
rule<OutputIteratorType, int()> testRule = eps[ref(lineNum) += 10]
<< lit("Line number ") << lit(ref(lineNum)) << lit(": ")
<< int_[_1 = _val] << eol;
generate(sink, testRule, 123);
generate(sink, testRule, 123);
std::cout << s;
return 0;
}