Encapsulate thread function with boost bind - c++

I am currently creating boost::threads like this:
boost::thread m_myThread; //member variable
//...
m_myThread = boost::thread(boost::bind(&MyClass::myThreadFunction, this));
This will start a thread which executes a member function "myThreadFunction".
I would like to encapsulate the starting of a new thread and use something like
boost::thread m_myThread; //member variable
//...
startAThread(&m_myThread, boost::bind(&MyClass::myThreadFunction, this), 123 /*some int argument*/);
I thought I could implement "startAThread" like this:
namespace internal
{
template <typename Callable>
void threadhelper(Callable func, int x)
{
doSomething(x);
func();
}
}
template <typename Callable>
void startAThread(boost::thread* threadToCreate, Callable func, int x)
{
*threadToCreate = boost::thread(boost::bind(internal::threadhelper<Callable>, func, x));
}
However, this fails to compile with
usr/include/boost/bind/bind.hpp: In member function 'void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = void (*)(boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, int), A = boost::_bi::list0, A1 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, A2 = boost::_bi::value<int>]':
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 = void (*)(boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, int), L = boost::_bi::list2<boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, boost::_bi::value<int> >]'
usr/include/boost/thread/detail/thread.hpp:61: instantiated from 'void boost::detail::thread_data<F>::run() [with F = boost::_bi::bind_t<void, void (*)(boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, int), boost::_bi::list2<boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >, boost::_bi::value<int> > >]'
MyClass.cpp:160: instantiated from here
usr/include/boost/bind/bind.hpp:313: error: conversion from 'void' to non-scalar type 'boost::_bi::bind_t<void, boost::_mfi::mf0<void, MyClass>, boost::_bi::list1<boost::_bi::value<MyClass*> > >' requested
What does this error mean? What's wrong with the code?
Thanks a lot!

Try
namespace internal
{
template <typename Callable>
void threadhelper(Callable func, int x)
{
doSomething(x);
func();
}
}
template <typename Callable>
void startAThread(boost::thread& threadToCreate, Callable func, int x) {
threadToCreate = boost::thread(boost::bind(&internal::threadhelper<Callable>, func, x));
}
I also used reference instead of pointer.

Related

How to properly extend std::thread to wrap spawned thread

Im trying to create a simple wrapper to be used by my application when creating threads in lew of std::thread.
The only purpose of using this app thread wrapper is to ensure some code gets invoked on every spawned thread consistently. I thought this would be trivial, but the std::thread constructor and argument passing is rather complex and Im getting very cryptic build errors here.
This is a simple example of what I'm trying to do:
#include <thread>
class AppThread : public std::thread
{
template< class Function, class... Args >
static void wrap( Function&& f, Args&&... args )
{
//Some code
f( std::forward<Args>( args )... );
}
public:
template< class Function, class... Args >
explicit AppThread( Function&& f, Args&&... args ) : std::thread( AppThread::wrap<Function,Args...>,
std::forward<Function>( f ), std::forward<Args>( args )... )
{}
};
void runA() {}
void runB( int x ) {}
main()
{
AppThread thread1 = AppThread( runA );
//AppThread thread2 = AppThread( runB, 5 );
}
I'd like to be able to drop in AppThread wherever std:thread is being used, so extending and overriding the constructor seems like the best approach. But passing those arguments through to my wrapped method causes this cascade of errors ( gcc 7.2 )
In file included from thread_wrap.cpp:1:0:
gcc-7.2.0/include/c++/7.2.0/thread: In instantiation of ‘struct std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >’:
gcc-7.2.0/include/c++/7.2.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(void (&)()); _Args = {void (&)()}]’
thread_wrap.cpp:15:130: required from ‘AppThread::AppThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]’
thread_wrap.cpp:24:41: required from here
gcc-7.2.0/include/c++/7.2.0/thread:240:2: error: no matching function for call to ‘std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_M_invoke(std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_Indices)’
operator()()
^~~~~~~~
gcc-7.2.0/include/c++/7.2.0/thread:231:4: note: candidate: template<long unsigned int ..._Ind> decltype (std::__invoke((_S_declval<_Ind>)()...)) std::thread::_Invoker<_Tuple>::_M_invoke(std::_Index_tuple<_Ind ...>) [with long unsigned int ..._Ind = {_Ind ...}; _Tuple = std::tuple<void (*)(void (&)()), void (*)()>]
_M_invoke(_Index_tuple<_Ind...>)
^~~~~~~~~
gcc-7.2.0/include/c++/7.2.0/thread:231:4: note: template argument deduction/substitution failed:
gcc-7.2.0/include/c++/7.2.0/thread: In substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1}]’:
gcc-7.2.0/include/c++/7.2.0/thread:240:2: required from ‘struct std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >’
gcc-7.2.0/include/c++/7.2.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(void (&)()); _Args = {void (&)()}]’
thread_wrap.cpp:15:130: required from ‘AppThread::AppThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]’
thread_wrap.cpp:24:41: required from here
gcc-7.2.0/include/c++/7.2.0/thread:233:29: error: no matching function for call to ‘__invoke(std::__tuple_element_t<0, std::tuple<void (*)(void (&)()), void (*)()> >, std::__tuple_element_t<1, std::tuple<void (*)(void (&)()), void (*)()> >)’
-> decltype(std::__invoke(_S_declval<_Ind>()...))
~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
In file included from gcc-7.2.0/include/c++/7.2.0/tuple:41:0,
from gcc-7.2.0/include/c++/7.2.0/bits/unique_ptr.h:37,
from gcc-7.2.0/include/c++/7.2.0/memory:80,
from gcc-7.2.0/include/c++/7.2.0/thread:39,
from thread_wrap.cpp:1:
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h:89:5: note: candidate: template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...)
__invoke(_Callable&& __fn, _Args&&... __args)
^~~~~~~~
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h:89:5: note: template argument deduction/substitution failed:
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h: In substitution of ‘template<class _Callable, class ... _Args> constexpr typename std::__invoke_result<_Functor, _ArgTypes>::type std::__invoke(_Callable&&, _Args&& ...) [with _Callable = void (*)(void (&)()); _Args = {void (*)()}]’:
gcc-7.2.0/include/c++/7.2.0/thread:233:29: required by substitution of ‘template<long unsigned int ..._Ind> decltype (std::__invoke(_S_declval<_Ind>()...)) std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >::_M_invoke<_Ind ...>(std::_Index_tuple<_Ind1 ...>) [with long unsigned int ..._Ind = {0, 1}]’
gcc-7.2.0/include/c++/7.2.0/thread:240:2: required from ‘struct std::thread::_Invoker<std::tuple<void (*)(void (&)()), void (*)()> >’
gcc-7.2.0/include/c++/7.2.0/thread:127:22: required from ‘std::thread::thread(_Callable&&, _Args&& ...) [with _Callable = void (&)(void (&)()); _Args = {void (&)()}]’
thread_wrap.cpp:15:130: required from ‘AppThread::AppThread(Function&&, Args&& ...) [with Function = void (&)(); Args = {}]’
thread_wrap.cpp:24:41: required from here
gcc-7.2.0/include/c++/7.2.0/bits/invoke.h:89:5: error: no type named ‘type’ in ‘struct std::__invoke_result<void (*)(void (&)()), void (*)()>’
Could definitely use some insight here!
Thanks
Here's an example of what I think Sam is driving at. As you can see, it is only a few lines of code so I'll leave it at that.
#include <iostream>
#include <thread>
#include <functional>
void preamble (void) { std::cout << "preamble\n"; }
template <class F, class ... Args> std::thread ThreadWrapper (F f, Args&& ... args)
{
return std::thread ([f, args...] () { preamble (); f (std::forward <Args...> (args...)); });
};
int main()
{
std::thread t = ThreadWrapper ([] (std::string s) { std::cout << s << "\n"; }, "42");
t.join ();
}
Output:
preamble
42
Live demo
I figured this out when I woke up this morning :)
Since std::thread decays all arguments it passes to the function, by the time it calls my wrap method the arguments are the decayed types. However, when I'm passing the template args to wrap<> it gets the undecayed types:
std::thread( AppThread::wrap<Function,Args...>,
Solution is simple, I need decay the types before instantiation the template wrap method:
std::thread( AppThread::wrap<std::decay_t<Function>,std::decay_t<Args>...>,

Compiler error boost::asio::placeholder::error with boost v1.69

The following code compiles and runs with the expected results ( 'done' on console after 3 seconds ) when build in codeblocks v17 with 32 bit g++ v5.1 and boost v1.63
#include <iostream>
#include <thread>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
namespace pinmed
{
class cTimedEvent
{
public:
cTimedEvent( boost::asio::io_service& ios )
: myTimer( ios )
{
}
/** Schedule one-off timed event
#param[in] msecs delay from now
#param[in] handler to call when delay expires
*/
template<
typename H >
void Schedule(
int msecs,
H handler )
{
myTimer.expires_from_now(
boost::posix_time::milliseconds( msecs ));
myTimer.async_wait( handler );
}
private:
boost::asio::deadline_timer myTimer;
};
class cClass
{
public:
cClass( boost::asio::io_service& ios )
: myTimedEvent( ios )
{
myTimedEvent.Schedule(
3000,
boost::bind(
&cClass::handler,
this,
boost::asio::placeholders::error) );
}
void handler(
const boost::system::system_error& e)
{
std::cout << "done\n";
}
private:
cTimedEvent myTimedEvent;
};
}
using namespace std;
int main()
{
boost::asio::io_service ios;
pinmed::cClass theClass( ios );
ios.run();
return 0;
}
However, when I "upgrade" to 64 bit g++ v8.2 with boost v1.69 then I get a horrible compiler error:
-------------- Build: Debug in test_timed (compiler: GNU GCC Compiler)---------------
g++.exe -Wall -fexceptions -g -std=c++11 -IC:\Users\James\code\boost\boost_1_69_0 -c C:\Users\James\code\test_timed\main.cpp -o obj\Debug\main.o
g++.exe -LC:\Users\James\code\boost\v1_63_gcc51\stage\lib -LC:\Users\James\code\nana-1.6.2\build\codeblocks -o \bin\test_timed.exe obj\Debug\main.o -lboost_thread-mgw51-mt-1_63 -lboost_system-mgw51-mt-1_63 -lboost_program_options-mgw51-mt-1_63 -lboost_filesystem-mgw51-mt-1_63 -lws2_32
In file included from C:\Users\James\code\boost\boost_1_69_0/boost/bind.hpp:22,
from C:\Users\James\code\test_timed\main.cpp:3:
C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp: In instantiation of 'void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>; A = boost::_bi::rrlist1<const boost::system::error_code&>; A1 = boost::_bi::value<pinmed::cClass*>; A2 = boost::arg<1> (*)()]':
C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:1306:50: required from 'boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()(A1&&) [with A1 = const boost::system::error_code&; R = void; F = boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>; L = boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()>; boost::_bi::bind_t<R, F, L>::result_type = void]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/detail/bind_handler.hpp:65:5: required from 'void boost::asio::detail::binder1<Handler, Arg1>::operator()() [with Handler = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >; Arg1 = boost::system::error_code]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/handler_invoke_hook.hpp:69:11: required from 'void boost::asio::asio_handler_invoke(Function&, ...) [with Function = boost::asio::detail::binder1<boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >, boost::system::error_code>]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/detail/handler_invoke_helpers.hpp:37:22: required from 'void boost_asio_handler_invoke_helpers::invoke(Function&, Context&) [with Function = boost::asio::detail::binder1<boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >, boost::system::error_code>; Context = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/detail/handler_work.hpp:82:46: required from 'void boost::asio::detail::handler_work<Handler, boost::asio::system_executor>::complete(Function&, Handler&) [with Function = boost::asio::detail::binder1<boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >, boost::system::error_code>; Handler = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/detail/wait_handler.hpp:72:7: required from 'static void boost::asio::detail::wait_handler<Handler>::do_complete(void*, boost::asio::detail::operation*, const boost::system::error_code&, std::size_t) [with Handler = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >; boost::asio::detail::operation = boost::asio::detail::win_iocp_operation; std::size_t = long long unsigned int]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/detail/wait_handler.hpp:39:15: required from 'boost::asio::detail::wait_handler<Handler>::wait_handler(Handler&) [with Handler = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/detail/deadline_timer_service.hpp:236:11: required from 'void boost::asio::detail::deadline_timer_service<Time_Traits>::async_wait(boost::asio::detail::deadline_timer_service<Time_Traits>::implementation_type&, Handler&) [with Handler = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >; Time_Traits = boost::asio::time_traits<boost::posix_time::ptime>]'
C:\Users\James\code\boost\boost_1_69_0/boost/asio/basic_deadline_timer.hpp:610:5: required from 'typename boost::asio::async_result<typename std::decay<_U1>::type, void(boost::system::error_code)>::return_type boost::asio::basic_deadline_timer<Time, TimeTraits>::async_wait(WaitHandler&&) [with WaitHandler = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >&; Time = boost::posix_time::ptime; TimeTraits = boost::asio::time_traits<boost::posix_time::ptime>; typename boost::asio::async_result<typename std::decay<_U1>::type, void(boost::system::error_code)>::return_type = void]'
C:\Users\James\code\test_timed\main.cpp:31:9: required from 'void pinmed::cTimedEvent::Schedule(int, H) [with H = boost::_bi::bind_t<void, boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>, boost::_bi::list2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()> >]'
C:\Users\James\code\test_timed\main.cpp:49:51: required from here
C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:319:35: error: no match for call to '(boost::_mfi::mf1<void, pinmed::cClass, const boost::system::system_error&>) (pinmed::cClass*&, const boost::system::error_code&)'
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn.hpp:215,
from C:\Users\James\code\boost\boost_1_69_0/boost/mem_fn.hpp:22,
from C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:26,
from C:\Users\James\code\boost\boost_1_69_0/boost/bind.hpp:22,
from C:\Users\James\code\test_timed\main.cpp:3:
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:163:7: note: candidate: 'R boost::_mfi::mf1<R, T, A1>::operator()(T*, A1) const [with R = void; T = pinmed::cClass; A1 = const boost::system::system_error&]'
R operator()(T * p, A1 a1) const
^~~~~~~~
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:163:7: note: no known conversion for argument 2 from 'const boost::system::error_code' to 'const boost::system::system_error&'
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:168:25: note: candidate: 'template<class U> R boost::_mfi::mf1<R, T, A1>::operator()(U&, A1) const [with U = U; R = void; T = pinmed::cClass; A1 = const boost::system::system_error&]'
template<class U> R operator()(U & u, A1 a1) const
^~~~~~~~
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:168:25: note: template argument deduction/substitution failed:
In file included from C:\Users\James\code\boost\boost_1_69_0/boost/bind.hpp:22,
from C:\Users\James\code\test_timed\main.cpp:3:
C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:319:35: note: cannot convert '(& a)->boost::_bi::rrlist1<const boost::system::error_code&>::operator[](boost::_bi::storage2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()>::a2_)' (type 'const boost::system::error_code') to type 'const boost::system::system_error&'
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn.hpp:215,
from C:\Users\James\code\boost\boost_1_69_0/boost/mem_fn.hpp:22,
from C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:26,
from C:\Users\James\code\boost\boost_1_69_0/boost/bind.hpp:22,
from C:\Users\James\code\test_timed\main.cpp:3:
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:176:25: note: candidate: 'template<class U> R boost::_mfi::mf1<R, T, A1>::operator()(const U&, A1) const [with U = U; R = void; T = pinmed::cClass; A1 = const boost::system::system_error&]'
template<class U> R operator()(U const & u, A1 a1) const
^~~~~~~~
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:176:25: note: template argument deduction/substitution failed:
In file included from C:\Users\James\code\boost\boost_1_69_0/boost/bind.hpp:22,
from C:\Users\James\code\test_timed\main.cpp:3:
C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:319:35: note: cannot convert '(& a)->boost::_bi::rrlist1<const boost::system::error_code&>::operator[](boost::_bi::storage2<boost::_bi::value<pinmed::cClass*>, boost::arg<1> (*)()>::a2_)' (type 'const boost::system::error_code') to type 'const boost::system::system_error&'
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_], a[base_type::a2_]);
~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn.hpp:215,
from C:\Users\James\code\boost\boost_1_69_0/boost/mem_fn.hpp:22,
from C:\Users\James\code\boost\boost_1_69_0/boost/bind/bind.hpp:26,
from C:\Users\James\code\boost\boost_1_69_0/boost/bind.hpp:22,
from C:\Users\James\code\test_timed\main.cpp:3:
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:184:7: note: candidate: 'R boost::_mfi::mf1<R, T, A1>::operator()(T&, A1) const [with R = void; T = pinmed::cClass; A1 = const boost::system::system_error&]'
R operator()(T & t, A1 a1) const
^~~~~~~~
C:\Users\James\code\boost\boost_1_69_0/boost/bind/mem_fn_template.hpp:184:7: note: no known conversion for argument 1 from 'pinmed::cClass*' to 'pinmed::cClass&'
Process terminated with status 1 (0 minute(s), 8 second(s))
1 error(s), 12 warning(s) (0 minute(s), 8 second(s))
What is the signature of handler of deadline_timer::async_wait method?
According to reference it is:
void handler(
const boost::system::error_code& error // Result of operation.
);
What is your signature?
void handler(
const boost::system::system_error& e)
{
std::cout << "done\n";
}
Change your handler to:
void handler(
const boost::system::error_code& e)
{
std::cout << "done\n";
}

Boost::bind a sigaction function reference to a instance

I would like to use a Linux kernel signal to asynchronously communicate the occurrence of an event from a module to a user-space application. I have this working in C in the following way:
void rcv_signal(int n, siginfo_t *info, void *unused)
{
// Do something interesting with the signal
}
// Register for updates from the kernel
int main(int argc, char *argv[])
{
struct sigaction sig;
sig.sa_sigaction = rcv_signal; // Function pointer
sig.sa_flags = SA_SIGINFO;
sigaction(SOME_CUSTOM_SIGNAL, &sig, NULL);
// Code to wait() then return
}
Now, I would like to move to C++ implementation. More specifically, I would like to use boost::function / boost::bind to bind the sa_sigaction to a method InputCapture::receive. However, I am struggling to get the correct function signature.
Here is the definition of the InputCapture Class:
class InputCapture
{
public: InputCapture(uint8_t intimer) : timer(_timer) {}
public: ~InputCapture() {}
private: void receive(int n, siginfo_t *info, void *unused) {}
private: uint8_t timer;
};
And here is the modified sa_sigaction:
// Register for updates from the kernel
struct sigaction sig;
sig.sa_sigaction = boost::function<void (int n, siginfo_t *info, void *unused)> (
boost::bind(&InputCapture::receive, this, _1));
sig.sa_flags = SA_SIGINFO;
sigaction(SOME_CUSTOM_SIGNAL, &sig, NULL);
However, I get the following compilation error:
In file included from /home/asymingt/export/rootfs/usr/include/boost/bind.hpp:22:0,
from /home/asymingt/Workspace/Source/roseline/timesync/src/stamp/LogicalStamp.hpp:12,
from /home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.hpp:4,
from /home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.cpp:1:
/home/asymingt/export/rootfs/usr/include/boost/bind/bind.hpp: In instantiation of ‘struct boost::_bi::result_traits’:
/home/asymingt/export/rootfs/usr/include/boost/bind/bind_template.hpp:15:48: required from ‘class boost::_bi::bind_t)(int, siginfo, void*), boost::_bi::list2, boost::arg<1> > >’
/home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.cpp:41:57: required from here
/home/asymingt/export/rootfs/usr/include/boost/bind/bind.hpp:69:37: error: ‘void (timesync::InputCapture::)(int, siginfo, void*)’ is not a class, struct, or union type
typedef typename F::result_type type;
^
/home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.cpp: In constructor ‘timesync::InputCapture::InputCapture(uint8_t)’:
/home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.cpp:40:19: error: cannot convert ‘boost::function’ to ‘void ()(int, siginfo_t, void*) {aka void ()(int, siginfo, void*)}’ in assignment
sig.sa_sigaction = boost::function (
^
In file included from /home/asymingt/export/rootfs/usr/include/boost/function/detail/maybe_include.hpp:28:0,
from /home/asymingt/export/rootfs/usr/include/boost/function/detail/function_iterate.hpp:14,
from /home/asymingt/export/rootfs/usr/include/boost/preprocessor/iteration/detail/iter/forward1.hpp:62,
from /home/asymingt/export/rootfs/usr/include/boost/function.hpp:64,
from /home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.cpp:3:
/home/asymingt/export/rootfs/usr/include/boost/function/function_template.hpp: In instantiation of ‘static void boost::detail::function::void_function_obj_invoker3::invoke(boost::detail::function::function_buffer&, T0, T1, T2) [with FunctionObj = boost::_bi::bind_t)(int, siginfo, void*), boost::_bi::list2, boost::arg<1> > >; R = void; T0 = int; T1 = siginfo*; T2 = void*]’:
/home/asymingt/export/rootfs/usr/include/boost/function/function_template.hpp:907:38: required from ‘void boost::function3::assign_to(Functor) [with Functor = boost::_bi::bind_t)(int, siginfo, void*), boost::_bi::list2, boost::arg<1> > >; R = void; T0 = int; T1 = siginfo*; T2 = void*]’
/home/asymingt/export/rootfs/usr/include/boost/function/function_template.hpp:722:7: required from ‘boost::function3::function3(Functor, typename boost::enable_if_c::value>::value, int>::type) [with Functor = boost::_bi::bind_t)(int, siginfo, void*), boost::_bi::list2, boost::arg<1> > >; R = void; T0 = int; T1 = siginfo*; T2 = void*; typename boost::enable_if_c::value>::value, int>::type = int]’
/home/asymingt/export/rootfs/usr/include/boost/function/function_template.hpp:1042:16: required from ‘boost::function::function(Functor, typename boost::enable_if_c::value>::value, int>::type) [with Functor = boost::_bi::bind_t)(int, siginfo, void*), boost::_bi::list2, boost::arg<1> > >; R = void; T0 = int; T1 = siginfo*; T2 = void*; typename boost::enable_if_c::value>::value, int>::type = int]’
/home/asymingt/Workspace/Source/roseline/timesync/src/stamp/InputCapture.cpp:41:58: required from here
/home/asymingt/export/rootfs/usr/include/boost/function/function_template.hpp:153:57: error: no match for call to ‘(boost::_bi::bind_t)(int, siginfo, void*), boost::_bi::list2, boost::arg<1> > >) (int&, siginfo*&, void*&)’
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
^
/home/asymingt/export/rootfs/usr/include/boost/function/function_template.hpp:75:36: note: in definition of macro ‘BOOST_FUNCTION_RETURN’
# define BOOST_FUNCTION_RETURN(X) X
Is what I am trying to achieve possible, and if so, where have I gone wrong?
You cannot do this.
Note that sigaction::sa_sigaction is a pointer to function. Neither boost::function, nor the return value of boost::bind are convertible to a function pointer!

boost::bind don't compile with member template function

I just write an simple example to test boost::bind. I use it to instantiate a template member function, but it won't compile with g++ 4.6.0. I don't know what's the problem.
Here's the code:
#include <boost/bind.hpp>
struct Functor
{
void operator()()
{
}
};
struct DerivedFinishAction
{
DerivedFinishAction()
{}
void Inc()
{
}
template <typename T>
void TmplFunc(T t)
{
(boost::bind(&DerivedFinishAction::BindFunc<T>, this , t))();
}
template <typename T>
void BindFunc(T t)
{
t();
}
void Func()
{
Functor f;
TmplFunc(f); // this is OK
TmplFunc(boost::bind(&DerivedFinishAction::Inc, this)); // compile error
}
};
int main(int argc, char *argv[])
{
return 0;
}
And g++ gives the following errors:
In file included from /usr/include/boost/bind.hpp:22:0,
from testBind.cpp:1:
/usr/include/boost/bind/bind.hpp: In member function ‘void boost::_bi::list2<A1, A2>::operator()(boost::_bi::type<void>, F&, A&, int) [with F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, A = boost::_bi::list0, A1 = boost::_bi::value<DerivedFinishAction*>, A2 = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’:
/usr/include/boost/bind/bind_template.hpp:20:59: instantiated from ‘boost::_bi::bind_t<R, F, L>::result_type boost::_bi::bind_t<R, F, L>::operator()() [with R = void, F = boost::_mfi::mf1<void, DerivedFinishAction, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, L = boost::_bi::list2<boost::_bi::value<DerivedFinishAction*>, boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > > >, boost::_bi::bind_t<R, F, L>::result_type = void]’
testBind.cpp:24:5: instantiated from ‘void DerivedFinishAction::TmplFunc(T) [with T = boost::_bi::bind_t<void, boost::_mfi::mf0<void, DerivedFinishAction>, boost::_bi::list1<boost::_bi::value<DerivedFinishAction*> > >]’
testBind.cpp:37:58: instantiated from here
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression
Can anybody help explain this? Why the first instantiation is OK while the second one causes compile error?
There's a (non-obvious) feature of boost::bind involved here. http://www.boost.org/libs/bind/#nested_binds
If you write:
void func1(int len) {return len+1;};
int func2(std::string str) {return str.length();};
assert(
boost::bind(func1, boost::bind(func2, _1) )("Hello")
== 6 );
boost::bind assumes that what you meant is "run func2 on "Hello", then run func1 on the result". This allows more interesting partial function application.
In your program, you have an expression which amounts to:
boost::bind(&DerivedFinishAction::BindFunc<...>,
this,
boost::bind(&DerivedFinishAction::Inc, this))
So boost::bind tries to figure out how to run DerivedFinishAction::Inc on it arguments, so it can pass that result into DerivedFinishAction::BindFunc<...>. But DerivedFinishAction::Inc returns void, which cannot be passed into DerivedFinishAction::BindFunc<...>. Thus you get a compiler error:
/usr/include/boost/bind/bind.hpp:313:9: error: invalid use of void expression
Edit: Per the documentation, you can use protect to achieve your desired behavior:
#include <boost/bind/protect.hpp>
...
TmplFunc(boost::protect(boost::bind(&DerivedFinishedAction::Inc, this))); // no longer an error
...

Why does this code using `::boost::bind` get a compiler error?

This code:
#include <boost/signals.hpp>
#include <boost/bind.hpp>
#include <boost/mem_fn.hpp>
#include <iostream>
class Recorder : public ::boost::signals::trackable {
public:
void signalled() {
const void *me = this;
::std::cerr << "Recorder at " << me << " signalled!\n";
}
};
void signalled()
{
::std::cerr << "Signalled!\n";
}
int main(int argc, const char *argv[])
{
::boost::signal<void ()> sig;
sig.connect(&signalled);
{
Recorder r;
sig.connect(::boost::bind(&Recorder::signalled, &r, _1));
sig();
}
sig();
return 0;
}
is generating these compiler errors:
In file included from move_constructor.cpp:2:
/usr/include/boost/bind.hpp: In instantiation of ‘boost::_bi::result_traits<boost::_bi::unspecified, void (Recorder::*)()>’:
/usr/include/boost/bind/bind_template.hpp:15: instantiated from ‘boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >’
move_constructor.cpp:25: instantiated from here
/usr/include/boost/bind.hpp:67: error: ‘void (Recorder::*)()’ is not a class, struct, or union type
In file included from /usr/include/boost/function/detail/maybe_include.hpp:13,
from /usr/include/boost/function/function0.hpp:11,
from /usr/include/boost/signals/signal_template.hpp:38,
from /usr/include/boost/signals/signal0.hpp:24,
from /usr/include/boost/signal.hpp:19,
from /usr/include/boost/signals.hpp:9,
from move_constructor.cpp:1:
/usr/include/boost/function/function_template.hpp: In static member function ‘static void boost::detail::function::void_function_obj_invoker0<FunctionObj, R>::invoke(boost::detail::function::function_buffer&) [with FunctionObj = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’:
/usr/include/boost/function/function_template.hpp:904: instantiated from ‘void boost::function0<R>::assign_to(Functor) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/function/function_template.hpp:720: instantiated from ‘boost::function0<R>::function0(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/function/function_template.hpp:1040: instantiated from ‘boost::function<R()>::function(Functor, typename boost::enable_if_c<boost::type_traits::ice_not::value, int>::type) [with Functor = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, R = void]’
/usr/include/boost/signals/slot.hpp:111: instantiated from ‘boost::slot<SlotFunction>::slot(const F&) [with F = boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >, SlotFunction = boost::function<void()>]’
move_constructor.cpp:25: instantiated from here
/usr/include/boost/function/function_template.hpp:152: error: no match for call to ‘(boost::_bi::bind_t<boost::_bi::unspecified, void (Recorder::*)(), boost::_bi::list2<boost::_bi::value<Recorder*>, boost::arg<1> > >) ()’
This is with g++ 4.4.1 on a Fedora 11 box with the Fedora 11 boost-1.37.0 package installed.
This code seems perfectly kosher to me. I don't understand what's going on here, and the maze of template expansion related errors is very confusing. Does anybody know what the problem is?
sig.connect(::boost::bind(&Recorder::signalled, &r, _1));
What is the _1 placeholder left for here? It's unneeded, connect expects void -> void function. If you'll remove the needless placeholder, the code will compile.
You provide &Recorder::signalled -- a member function of type void Recorder::(void), correctly bind a Recorder pointer, changing it to void -> void, and then additionally leave a placeholder _1 -- what is obviously wrong.