[Statechart] Passing reference to create_processor()

The Boost reference states that boost::ref can be used to pass an argument to statechart::fifo_scheduler::create_processor by reference instead of by value. I haven't been able to get this to work if the argument type derives from boost::noncopyable. It appears that the create_processor implementation instantiates code that attempts to copy the argument. Here's an example. Note that this compiles and runs sucessfully if Object does not derive from boost::noncopyable. Thanks, Steve Hawkes ---- #include <boost/statechart/asynchronous_state_machine.hpp> #include <boost/statechart/fifo_scheduler.hpp> #include <boost/statechart/simple_state.hpp> #include <boost/noncopyable.hpp> #include <boost/ref.hpp> #include <iostream> class Object : public boost::noncopyable { }; struct Initial; struct Test : boost::statechart::asynchronous_state_machine<Test, Initial> { public: Test(my_context ctx, Object& arg1) : my_base(ctx) { } }; struct Initial : boost::statechart::simple_state<Initial, Test> { }; int main() { Object value; boost::statechart::fifo_scheduler<> scheduler; const boost::statechart::fifo_scheduler<>::processor_handle processor1 = scheduler.create_processor <Test, Object&> (boost::ref(value)); return (0); } ---- Here's the compiler error: ---- g++ -Wall -lboost_system-mt -lboost_thread-mt -o test test.cc /usr/include/boost/noncopyable.hpp: In copy constructor 'Object::Object(const Object&)': test.cc:9: instantiated from 'typename boost::statechart::processor_container<boost::statechart::fifo_scheduler <FifoWorker, Allocator>, typename FifoWorker::work_item, Allocator>::processor_handle boost::statechart::fifo_scheduler<FifoWorker, Allocator>::create_processor(Arg1) [with Processor = Test, Arg1 = Object&, FifoWorker = boost::statechart::fifo_worker<std::allocator<void> >, Allocator = std::allocator<void>]' test.cc:36: instantiated from here /usr/include/boost/noncopyable.hpp:27: error: 'boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)' is private test.cc:9: error: within this context /usr/include/boost/statechart/fifo_scheduler.hpp: In member function 'typename boost::statechart::processor_container<boost::statechart::fifo_scheduler <FifoWorker, Allocator>, typename FifoWorker::work_item, Allocator>::processor_handle boost::statechart::fifo_scheduler<FifoWorker, Allocator>::create_processor(Arg1) [with Processor = Test, Arg1 = Object&, FifoWorker = boost::statechart::fifo_worker<std::allocator<void> >, Allocator = std::allocator<void>]': /usr/include/boost/statechart/fifo_scheduler.hpp:63: note: synthesized method 'Object::Object(const Object&)' first required here /usr/include/boost/statechart/fifo_scheduler.hpp:63: error: initializing argument 3 of 'WorkItem boost::statechart::processor_container<Scheduler, WorkItem, Allocator>::create_processor(boost::weak_ptr<std::auto_ptr<boost::statec hart::event_processor<Scheduler> > >&, Scheduler&, Arg1) [with Processor = Test, Arg1 = Object, Scheduler = boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::al locator<void> >, std::allocator<void> >, WorkItem = boost::function0<void>, Allocator = std::allocator<void>]'

Hawkes Steve-FSH016 wrote:
It appears that the create_processor implementation instantiates code that attempts to copy the argument.
It does, and this is why you must pass boost::ref wrapper instead of the reference itself.
processor1 = scheduler.create_processor <Test, Object&> (boost::ref(value));
Here you instruct the compiler to convert the parameter into Object &, and therefore boost::ref has no effect, as the conversion takes place "before" the create_processor call. Just omit the "Object &" template parameter and let the compiler deduce it and the code should compile. HTH Juraj Ivančić

It appears that the create_processor implementation instantiates code that attempts to copy the argument.
It does, and this is why you must pass boost::ref wrapper instead of the reference itself.
processor1 = scheduler.create_processor <Test, Object&> (boost::ref(value));
Here you instruct the compiler to convert the parameter into Object &, and therefore boost::ref has no effect, as the conversion takes place "before" the create_processor call. Just omit the "Object &" template parameter and let the compiler deduce it and the code should compile.
HTH Juraj Ivančić
Good point. I had tried this, as well as specifying the template parameter type as boost::reference_wrapper<Object>. Here is the result with create_processor<Test>(boost::ref(value)): g++ -Wall -o test test.cc /usr/include/boost/bind.hpp: In member function 'void boost::_bi::list4<A1, A2, A3, A4>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, A = boost::_bi::list0, A1 = boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, A2 = boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, A3 = boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, A4 = boost::reference_wrapper<Object>]': /usr/include/boost/bind/bind_template.hpp:20: instantiated from 'typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, L = boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> >]' /usr/include/boost/function/function_template.hpp:152: instantiated from 'static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<void, boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> > >, R = void]' /usr/include/boost/function/function_template.hpp:931: instantiated from 'void boost::function0<R>::assign_to_a(Functor, Allocator) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> > >, Allocator = std::allocator<void>, R = void]' /usr/include/boost/function/function_template.hpp:733: instantiated from 'boost::function0<R>::function0(Functor, Allocator, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> > >, Allocator = std::allocator<void>, R = void]' /usr/include/boost/statechart/processor_container.hpp:112: instantiated from 'WorkItem boost::statechart::processor_container<Scheduler, WorkItem, Allocator>::create_processor(boost::weak_ptr<std::auto_ptr<boost::statechart::event_processor<Scheduler> > >&, Scheduler&, Arg1) [with Processor = Test, Arg1 = boost::reference_wrapper<Object>, Scheduler = boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, WorkItem = boost::function0<void>, Allocator = std::allocator<void>]' /usr/include/boost/statechart/fifo_scheduler.hpp:63: instantiated from 'typename boost::statechart::processor_container<boost::statechart::fifo_scheduler<FifoWorker, Allocator>, typename FifoWorker::work_item, Allocator>::processor_handle boost::statechart::fifo_scheduler<FifoWorker, Allocator>::create_processor(Arg1) [with Processor = Test, Arg1 = boost::reference_wrapper<Object>, FifoWorker = boost::statechart::fifo_worker<std::allocator<void> >, Allocator = std::allocator<void>]' test.cc:36: instantiated from here /usr/include/boost/bind.hpp:436: error: no match for call to '(boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >) (boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*&, boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, Object&)' /usr/include/boost/bind/mem_fn_template.hpp:382: note: candidates are: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T*, A1, A2, A3) const [with R = void, T = boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, A1 = const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, A2 = const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, A3 = boost::reference_wrapper<Object>] /usr/include/boost/bind/mem_fn_template.hpp:401: note: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T&, A1, A2, A3) const [with R = void, T = boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, A1 = const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, A2 = const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, A3 = boost::reference_wrapper<Object>] Compilation exited abnormally with code 1 at Fri Apr 10 09:19:58 And here is the identical result with create_processor<Test, boost::reference_wrapper<Object> >(boost::ref(Object)): g++ -Wall -o test test.cc /usr/include/boost/bind.hpp: In member function 'void boost::_bi::list4<A1, A2, A3, A4>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, A = boost::_bi::list0, A1 = boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, A2 = boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, A3 = boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, A4 = boost::reference_wrapper<Object>]': /usr/include/boost/bind/bind_template.hpp:20: instantiated from 'typename boost::_bi::result_traits<R, F>::type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, L = boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> >]' /usr/include/boost/function/function_template.hpp:152: instantiated from 'static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<void, boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> > >, R = void]' /usr/include/boost/function/function_template.hpp:931: instantiated from 'void boost::function0<R>::assign_to_a(Functor, Allocator) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> > >, Allocator = std::allocator<void>, R = void]' /usr/include/boost/function/function_template.hpp:733: instantiated from 'boost::function0<R>::function0(Functor, Allocator, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<void, boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >, boost::_bi::list4<boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*>, boost::_bi::value<boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > > >, boost::_bi::value<boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context>, boost::reference_wrapper<Object> > >, Allocator = std::allocator<void>, R = void]' /usr/include/boost/statechart/processor_container.hpp:112: instantiated from 'WorkItem boost::statechart::processor_container<Scheduler, WorkItem, Allocator>::create_processor(boost::weak_ptr<std::auto_ptr<boost::statechart::event_processor<Scheduler> > >&, Scheduler&, Arg1) [with Processor = Test, Arg1 = boost::reference_wrapper<Object>, Scheduler = boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, WorkItem = boost::function0<void>, Allocator = std::allocator<void>]' /usr/include/boost/statechart/fifo_scheduler.hpp:63: instantiated from 'typename boost::statechart::processor_container<boost::statechart::fifo_scheduler<FifoWorker, Allocator>, typename FifoWorker::work_item, Allocator>::processor_handle boost::statechart::fifo_scheduler<FifoWorker, Allocator>::create_processor(Arg1) [with Processor = Test, Arg1 = boost::reference_wrapper<Object>, FifoWorker = boost::statechart::fifo_worker<std::allocator<void> >, Allocator = std::allocator<void>]' test.cc:36: instantiated from here /usr/include/boost/bind.hpp:436: error: no match for call to '(boost::_mfi::mf3<void, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, boost::reference_wrapper<Object> >) (boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >*&, boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, Object&)' /usr/include/boost/bind/mem_fn_template.hpp:382: note: candidates are: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T*, A1, A2, A3) const [with R = void, T = boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, A1 = const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, A2 = const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, A3 = boost::reference_wrapper<Object>] /usr/include/boost/bind/mem_fn_template.hpp:401: note: R boost::_mfi::mf3<R, T, A1, A2, A3>::operator()(T&, A1, A2, A3) const [with R = void, T = boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >, A1 = const boost::shared_ptr<std::auto_ptr<boost::statechart::event_processor<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> > > > >&, A2 = const boost::statechart::processor_container<boost::statechart::fifo_scheduler<boost::statechart::fifo_worker<std::allocator<void> >, std::allocator<void> >, boost::function0<void>, std::allocator<void> >::processor_context&, A3 = boost::reference_wrapper<Object>] Compilation exited abnormally with code 1 at Fri Apr 10 09:30:38

Hi Steve The usage as suggested by Juraj (thanks also, BTW) should work, so this is a bug. I'll look into it and should have an answer by the end of next week. Thanks & Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

I've got the same problem now. Is there any solution or workaround so far? Thanks!

Steve & Igor, I must admit I don't currently see why this happens, I'll probably have to produce a minimal repro and ask bind experts for help. For now, you might want to try the attached work-around (note the additional conversion operator in class Object). This compiles for me on VC9.0 and seems to work as expected. Yes, this is an ugly hack but it has the advantage that it can be reverted relatively quickly once I've figured out how to fix this bug. Alternatively, you could change Test so that it accepts an Object * (or any smart ptr) rather than an Object &, but that would of course require changes in several places in the code, not just one as in my suggestion. For now I'll have to stop here, I'll pursue this further next weekend. HTH, Andreas #include <boost/statechart/asynchronous_state_machine.hpp> #include <boost/statechart/fifo_scheduler.hpp> #include <boost/statechart/simple_state.hpp> #include <boost/noncopyable.hpp> #include <boost/ref.hpp> class Object : public boost::noncopyable { public: Object() {} operator boost::reference_wrapper<Object>() // <-- HERE { return boost::ref(*this); } }; struct Initial; struct Test : boost::statechart::asynchronous_state_machine<Test, Initial> { public: Test(my_context ctx, Object &) : my_base(ctx) {} }; struct Initial : boost::statechart::simple_state<Initial, Test> {}; int main() { Object value; boost::statechart::fifo_scheduler<> scheduler; const boost::statechart::fifo_scheduler<>::processor_handle processor1 = scheduler.create_processor<Test>(boost::ref(value)); scheduler.initiate_processor(processor1); scheduler.operator ()(); return 0; }

Andreas Huber:
I must admit I don't currently see why this happens, I'll probably have to produce a minimal repro and ask bind experts for help.
It happens because ultimately you produce a bind expression such as boost::bind( pImpl, this, ..., boost::ref( value ) ) and the ref is interpreted by bind as a reference to 'value'. But your Arg1 remains a reference_wrapper. You'll probably need to convert ArgN parameters that are of the form reference_wrapper<X> to X& before instantiating create_processor_implN.

Hi Peter Thanks for looking at this!
I must admit I don't currently see why this happens, I'll probably have to produce a minimal repro and ask bind experts for help.
It happens because ultimately you produce a bind expression such as
boost::bind( pImpl, this, ..., boost::ref( value ) )
and the ref is interpreted by bind as a reference to 'value'. But your Arg1 remains a reference_wrapper. You'll probably need to convert ArgN parameters that are of the form reference_wrapper<X> to X& before instantiating create_processor_implN.
Ok, lets see whether I understand this correctly: #include <boost/noncopyable.hpp> #include <boost/bind.hpp> class Object : public boost::noncopyable {}; void func1(Object &) {} void func2(boost::reference_wrapper<Object>) {} int main() { Object value; boost::bind(&func1, boost::ref(value))(); // 1: compiles boost::bind(&func2, boost::ref(value))(); // 2: doesn't return 0; } 2 doesn't compile because bind internally assumes that the target function accepts a T & parameter for each reference_wrapper<T> argument, correct? If so, then I guess I should use boost::unwrap_reference<Arg1>::type instead of Arg1 to instantiate create_processor_impl1. Thanks & Regards, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Hi Steve, Igor A fix for this bug has been checked into the trunk: https://svn.boost.org/trac/boost/changeset/52616 Tests run fine for me on VC9.0. If you're using a different compiler and feeling adventurous, you may use the trunk version of Statechart right away. Otherwise, please wait until testrunners have caught up (rev 52616), please see ... http://www.boost.org/development/tests/trunk/developer/statechart.html ... and make sure that the fields at the intersection of FifoSchedulerTest* and your compiler show all green. I'll be monitoring the test results over the next few days, and be fixing bugs as they appear. As soon as tests have been run on most platforms I'll merge to the release branch, so that this fix should make it into the 1.39 Boost release. Sorry for the trouble and the delay... HTH, -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.

Hi Steve, Igor
A fix for this bug has been checked into the trunk:
Thank you very much!

A fix for this bug has been checked into the trunk:
It turns out that I accidentally used a non-standard feature of MSVC, presumably fixed in https://svn.boost.org/trac/boost/changeset/52620
As soon as tests have been run on most platforms I'll merge to the release branch, so that this fix should make it into the 1.39 Boost release.
I just noticed that the beta is already out, so this will probably have to wait until 1.40. -- Andreas Huber When replying by private email, please remove the words spam and trap from the address shown in the header.
participants (5)
-
Andreas Huber
-
Hawkes Steve-FSH016
-
Igor R
-
Juraj Ivančić
-
Peter Dimov