1

I am using boost io_service to run methods asynchronously:

void my_class::completion_handler()
{
  ...
}
m_io_service.post(boost::bind(&my_class::completion_handler, this));

I would like to use lambda expression instead of boost::bind (see below) in order to avoid creating method for each handler but I am using a C++ compiler that does not support C++11 fully:

m_io_service.post([this](){ ... });

Is it possible to have the same behavior by using phoenix lambda ?

Thank you.

user1886318
  • 235
  • 3
  • 11

1 Answers1

1

Yes that's possible.

Most notable difference is the placeholders (don't use std::place_holders::_1, _2... but boost::phoenix::arg_names::arg1, arg2...).

However, simply replacing boost::bind with std::bind, boost::lambda::bind or boost::phoenix::bind is ultimately useless of course.

Instead you could use Phoenix actors to compose "lambdas", like e.g.

namespace phx = boost::phoenix;

boost::mutex mx;
boost::condition_variable cv;
boost::unique_lock<boost::mutex> lk(mx);
vc.wait(lk, phx::ref(m_queue_size) > 0);

Member invocations are tricky in that respect.

The good news is that Phoenix comes with implementations of many STL operations like size(), empty(), push_back() etc.

Similar use of Phoenix in this queue implementation: Boost group_threads Maximal number of parallel thread and e.g. asio::io_service and thread_group lifecycle issue).

boost::fusion::function<>

You can adapt free functions with BOOST_PHOENIX_ADAPT_FUNCTION and function objects with BOOST_PHOENIX_ADAPT_CALLABLE. However in the latter case it's probably more elegant to use boost::fusion::function<>:

struct MyType {
    MyType()
        : complete_(complete_f { this }) 
    { }

    void doSomething() { }

   private:    
     struct complete_f {
         MyType* _this;
         void operator()() const {
             // do something with _this, e.g
             this->doSomething();
         }
     };

     boost::phoenix::function<complete_f> complete_;
};
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks for your reply. So is it not possible to make easier by using phoenix::lambda directly ? Like this `m_io_service.post(phoenix::lambda(local-declarations) [ lambda-body ]);` – user1886318 Dec 28 '17 at 14:33
  • Nope. There's http://www.boost.org/doc/libs/1_66_0/libs/phoenix/doc/html/phoenix/modules/operator.html#phoenix.modules.operator.member_pointer_operator but it doesn't eexactly make things easier IYAM – sehe Dec 28 '17 at 14:35
  • 1
    And, no, lambda is just a way to make a named actor with potentially multiple statements. But you'll still have to awkwardly bind the member function invocation (because C++ doesn't have transparent proxy types and/or `operator.`) – sehe Dec 28 '17 at 14:36