I am using boost spirit qi to parse inbound data then dispatch the correct functionality depending on it's content.
I am using boost::signals
to manage the callbacks; my problem is that I don't seem to be able to use phoenix bind with the boost signals.
Consider the following test case:
#include <boost/signals.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <iostream>
void f(int i) {
std::cout << i << '\n';
}
int main() {
boost::signal<void(int)> sig;
sig.connect(f);
std::string s="123";
auto first=s.cbegin(), last=s.cend();
boost::spirit::qi::parse(
first, last,
(
boost::spirit::qi::int_
[
boost::phoenix::bind(sig, boost::spirit::qi::_1)
]
)
);
}
This doesn't compile, spitting out a wall of errors.
Note that if I replace the phoenix bind line with
boost::phoenix::bind(&f, boost::spirit::qi::_1)
it works as expected (however due to the larger design of the program this isn't possible).
Thanks in advance.
As noted by Igor R. in the comments, your original error was due to the fact that phoenix::bind
copies its arguments by default and boost::signal
s are non-copyable. When you use phoenix::ref
to solve that, another error emerges, this one caused by Boost.Phoenix v2's inability to find the returned type. This can also be easily solved by defining BOOST_SPIRIT_USE_PHOENIX_V3
.
#include <boost/signals.hpp>
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <iostream>
void f(int i) {
std::cout << i << '\n';
}
int main() {
boost::signal<void(int)> sig;
sig.connect(f);
std::string s="123";
auto first=s.cbegin(), last=s.cend();
boost::spirit::qi::parse(
first, last,
(
boost::spirit::qi::int_
[
boost::phoenix::bind(boost::phoenix::ref(sig), boost::spirit::qi::_1)
]
)
);
}