Pergunta

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.

Foi útil?

Solução

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::signals 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)
             ]
         )
     ); 
 }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top