In a continuation from this question. I'm trying to bind a given function that returns something-other-than void to be able to simply call f() later. However the following code fails to compile on GCC 4.4. It compiles on VS 2010, but the resulting program crashes.
template<typename RetType>
void _hideRet(std::function<RetType ()> func, RetType * ret)
{
*ret = func();
}
template<typename FuncType, typename RetType, typename ParamType>
std::function<void ()> registerFunc(FuncType func, RetType * ret, ParamType param)
{
auto f = std::bind(func, std::forward<ParamType>(param));
return std::bind(_hideRet<RetType>, f, ret);
}
int myFunction(std::string text)
{
std::cout << text << std::endl;
return 42;
}
int main()
{
int ret = 0;
auto f = registerFunc(myFunction, &ret, "text");
f();
std::cout << ret << std::endl;
return 0;
}
GCC produces this crazy message:
In file included from /usr/include/c++/4.4/functional:70,
from func.cpp:4:
/usr/include/c++/4.4/tr1_impl/functional: In member function ‘typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args, std::is_bind_expression::value, (std::is_placeholder::value > 0)>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::__call(const std::tuple<_UElements ...>&, std::_Index_tuple<_Indexes ...>) [with _Args = , int ..._Indexes = 0, 1, _Functor = void (*)(std::function<int()>, int*), _Bound_args = std::_Bind<int (*(const char*))(std::string)>, int*]’:
/usr/include/c++/4.4/tr1_impl/functional:1191: instantiated from ‘typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args, std::is_bind_expression::value, (std::is_placeholder::value > 0)>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) [with _Args = , _Functor = void (*)(std::function<int()>, int*), _Bound_args = std::_Bind<int (*(const char*))(std::string)>, int*]’
/usr/include/c++/4.4/tr1_impl/functional:1668: instantiated from ‘static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::_Bind<void (*(std::_Bind<int (*(const char*))(std::string)>, int*))(std::function<int()>, int*)>, _ArgTypes = ]’
/usr/include/c++/4.4/tr1_impl/functional:2005: instantiated from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::is_integral::value), std::function<_Res(_ArgTypes ...)>::_Useless>::__type) [with _Functor = std::_Bind<void (*(std::_Bind<int (*(const char*))(std::string)>, int*))(std::function<int()>, int*)>, _Res = void, _ArgTypes = ]’
func.cpp:16: instantiated from ‘std::function<void()> registerFunc(FuncType, RetType*, ParamType) [with FuncType = int (*)(std::string), RetType = int, ParamType = const char*]’
func.cpp:28: instantiated from here
/usr/include/c++/4.4/tr1_impl/functional:1137: error: invalid conversion from ‘int’ to ‘std::_M_clear_type*’
/usr/include/c++/4.4/tr1_impl/functional:1137: error: initializing argument 1 of ‘std::function<_Res(_ArgTypes ...)>::function(std::_M_clear_type*) [with _Res = int, _ArgTypes = ]’
I don't have enough knowledge of the inner STL workings to make anything out of that.
However while experimenting I found out that if I remove the second std::bind call from the registerFunc template like this:
template<typename FuncType, typename RetType, typename ParamType>
std::function<RetType ()> registerFunc(FuncType func, RetType *, ParamType param)
{
return std::bind(func, std::forward<ParamType>(param));
}
// in main
auto tmp = registerFunc(myFunction, &ret, "text");
auto f = std::bind(_hideRet<int>, tmp, &ret);
f();
The code works as expected both in VS and GCC. So my conclusion is that the problem is in calling std::bind(_hideRet<RetType>, ...) from within a template function. The question is why is that a problem? And more importantly how to fix this?
This is absolutely amazing, but replacing :
auto f = std::bind(func, std::forward<ParamType>(param));
return std::bind(_hideRet<RetType>, f, ret);
by :
std::function<RetType ()> f = std::bind(func, std::forward<ParamType>(param));
return std::bind(_hideRet<RetType>, f, ret);
under Visual Studio 2010 runs as expected (which is essentially what you did by moving the second bind out of registerFunc). I'm trying to make sense out of it, but until then, that seems like a workaround for your issue,
Related
This is my (simplified) code where I'm trying to call async forwarding arguments:
template<typename Ret, typename ... Args>
class CallbackAsyncTask {
public:
CallbackAsyncTask() {
}
virtual ~CallbackAsyncTask() = default;
void execute( Args&& ... args ) {
execute(&CallbackAsyncTask<Ret, Args...>::onBackground, this, std::forward<Args>(args)...);
}
protected:
virtual Ret onBackground( Args& ... args ) = 0;
template<typename Fn, typename ... Argss>
void execute( Fn&& fn, Argss&& ... args ) noexcept(false) {
std::async(std::launch::async, std::forward<Fn>(fn), std::forward<Argss>(args)...);
}
};
class Child: public CallbackAsyncTask<int, int> {
public:
virtual int onBackground( int& i ) {
return i;
}
};
int main() {
Child c;
c.execute(15);
return 0;
}
I get this error:
../main.cpp: In instantiation of ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’:
../main.cpp:27:98: required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17: required from here
../main.cpp:33:90: error: no matching function for call to ‘async(std::launch, int (CallbackAsyncTask<int, int>::*)(int&), CallbackAsyncTask<int, int>* const, int)’
std::async(std::launch::async, std::forward<Fn>(fn), std::forward<Argss>(args)...);
^
../main.cpp:33:90: note: candidates are:
In file included from ../main.cpp:13:0:
/usr/include/c++/4.8.2/future:1532:5: note: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...)
async(launch __policy, _Fn&& __fn, _Args&&... __args)
^
/usr/include/c++/4.8.2/future:1532:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.8.2/future: In substitution of ‘template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(std::launch, _Fn&&, _Args&& ...) [with _Fn = int (CallbackAsyncTask<int, int>::*)(int&); _Args = {CallbackAsyncTask<int, int>* const, int}]’:
../main.cpp:33:90: required from ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’
../main.cpp:27:98: required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17: required from here
/usr/include/c++/4.8.2/future:1532:5: error: no type named ‘type’ in ‘class std::result_of<int (CallbackAsyncTask<int, int>::*(CallbackAsyncTask<int, int>*, int))(int&)>’
../main.cpp: In instantiation of ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’:
../main.cpp:27:98: required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17: required from here
/usr/include/c++/4.8.2/future:1552:5: note: template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...)
async(_Fn&& __fn, _Args&&... __args)
^
/usr/include/c++/4.8.2/future:1552:5: note: template argument deduction/substitution failed:
/usr/include/c++/4.8.2/future: In substitution of ‘template<class _Fn, class ... _Args> std::future<typename std::result_of<_Functor(_ArgTypes ...)>::type> std::async(_Fn&&, _Args&& ...) [with _Fn = std::launch; _Args = {int (CallbackAsyncTask<int, int>::*)(int&), CallbackAsyncTask<int, int>* const, int}]’:
../main.cpp:33:90: required from ‘void CallbackAsyncTask<Ret, Args>::execute(Fn&&, Argss&& ...) [with Fn = int (CallbackAsyncTask<int, int>::*)(int&); Argss = {CallbackAsyncTask<int, int>* const, int}; Ret = int; Args = {int}]’
../main.cpp:27:98: required from ‘void CallbackAsyncTask<Ret, Args>::execute(Args&& ...) [with Ret = int; Args = {int}]’
../main.cpp:46:17: required from here
/usr/include/c++/4.8.2/future:1552:5: error: no type named ‘type’ in ‘class std::result_of<std::launch(int (CallbackAsyncTask<int, int>::*)(int&), CallbackAsyncTask<int, int>*, int)>’
What I am missing? Compiler Gcc 4.8.3
The root cause is these two lines
virtual Ret onBackground( Args& ... args ) = 0;
virtual int onBackground( int& i )
When launching the task, the arguments are converted either directly or as if by the std::thread constructor. That one does decay_copy on the arguments when invoking the callable, so a non-const lvalue reference cannot bind to the argument.
Change the way onBackground accepts arguments. For instance, a const lvalue refernce works. See live.
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>...>,
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!
I have this minimal not-working example of code
#include <future>
int main()
{
auto intTask = std::packaged_task<int()>( []()->int{ return 5; } );
std::packaged_task<void()> voidTask{ std::move(intTask) };
}
Why doesn't it compile (on gcc 4.8.1)? I suspect, the reason is, that std::packaged_task stores the lambda internally inside an std::function which needs a CopyConstructible argument. However, std::packaged_task is move-only. Is this a bug? What does the standard say about it? In my opinion std::packaged_task should not need a CopyConstructible argument, but a MoveConstructible argument should be enough.
By the way, when I replace std::packaged_task<int()> by std::packaged_task<void()> everything compiles fine.
GCC 4.8.1 is giving me this error message:
In file included from /usr/include/c++/4.6/future:38:0,
from ../cpp11test/main.cpp:160:
/usr/include/c++/4.6/functional: In static member function 'static void std::_Function_base::_Base_manager<_Functor>::_M_clone(std::_Any_data&, const std::_Any_data&, std::false_type) [with _Functor = std::packaged_task<int()>, std::false_type = std::integral_constant<bool, false>]':
/usr/include/c++/4.6/functional:1652:8: instantiated from 'static bool std::_Function_base::_Base_manager<_Functor>::_M_manager(std::_Any_data&, const std::_Any_data&, std::_Manager_operation) [with _Functor = std::packaged_task<int()>]'
/usr/include/c++/4.6/functional:2149:6: instantiated from 'std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = std::packaged_task<int()>, _Res = void, _ArgTypes = {}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void()>::_Useless]'
/usr/include/c++/4.6/bits/shared_ptr_base.h:410:4: instantiated from 'std::_Sp_counted_ptr_inplace<_Tp, _Alloc, _Lp>::_Sp_counted_ptr_inplace(_Alloc, _Args&& ...) [with _Args = {std::packaged_task<int()>}, _Tp = std::__future_base::_Task_state<void()>, _Alloc = std::allocator<std::__future_base::_Task_state<void()> >, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]'
/usr/include/c++/4.6/bits/shared_ptr_base.h:518:8: instantiated from 'std::__shared_count<_Lp>::__shared_count(std::_Sp_make_shared_tag, _Tp*, const _Alloc&, _Args&& ...) [with _Tp = std::__future_base::_Task_state<void()>, _Alloc = std::allocator<std::__future_base::_Task_state<void()> >, _Args = {std::packaged_task<int()>}, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]'
/usr/include/c++/4.6/bits/shared_ptr_base.h:987:35: instantiated from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<std::__future_base::_Task_state<void()> >, _Args = {std::packaged_task<int()>}, _Tp = std::__future_base::_Task_state<void()>, __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]'
/usr/include/c++/4.6/bits/shared_ptr.h:317:64: instantiated from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = std::allocator<std::__future_base::_Task_state<void()> >, _Args = {std::packaged_task<int()>}, _Tp = std::__future_base::_Task_state<void()>]'
/usr/include/c++/4.6/bits/shared_ptr.h:535:39: instantiated from 'std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = std::__future_base::_Task_state<void()>, _Alloc = std::allocator<std::__future_base::_Task_state<void()> >, _Args = {std::packaged_task<int()>}]'
/usr/include/c++/4.6/bits/shared_ptr.h:551:42: instantiated from 'std::shared_ptr<_Tp1> std::make_shared(_Args&& ...) [with _Tp = std::__future_base::_Task_state<void()>, _Args = {std::packaged_task<int()>}]'
/usr/include/c++/4.6/future:1223:66: instantiated from 'std::packaged_task<_Res(_ArgTypes ...)>::packaged_task(_Fn&&) [with _Fn = std::packaged_task<int()>, _Res = void, _ArgTypes = {}]'
../cpp11test/main.cpp:165:61: instantiated from here
/usr/include/c++/4.6/functional:1616:4: error: use of deleted function 'std::packaged_task<_Res(_ArgTypes ...)>::packaged_task(std::packaged_task<_Res(_ArgTypes ...)>&) [with _Res = int, _ArgTypes = {}, std::packaged_task<_Res(_ArgTypes ...)> = std::packaged_task<int()>]'
/usr/include/c++/4.6/future:1244:7: error: declared here
UPDATE: I have written the following test program. It seems to support the assumption that the reason is missing CopyConstructability. Again, what are the requirements on the type of the object from which an std::packaged_task may be constructed?
#include <future>
struct Functor {
Functor() {}
Functor( const Functor & ) {} // without this line it doesn't compile
Functor( Functor && ) {}
int operator()(){ return 5; }
};
int main() {
auto intTask = std::packaged_task<int()>( Functor{} );
}
Indeed, packaged_task only has a moving constructor (30.6.9/2):
template <class F> explicit packaged_task(F&& f);
However, your problem is the explicit constructor. So write it like this:
std::packaged_task<int()> pt([]() -> int { return 1; });
Complete example:
#include <future>
#include <thread>
int main()
{
std::packaged_task<int()> intTask([]() -> int { return 5; } );
auto f = intTask.get_future();
std::thread(std::move(intTask)).detach();
return f.get();
}
No. You just can't move a packaged_task<int ()> into a packaged_task<void ()>. These types a unrelated and cannot be move-assigned or move-constructed from each other. If you for some reason really want to do that you can "swallow" the result of the int () like this
The standard (as of N3690) doesn't state anything explicitly about the requirements of the type F in
template <class R, class... ArgTypes>
template <class F>
packaged_task<R(ArgTypes...)>::packaged_task(F&& f);
(see 30.6.9.1) However, it states that
Invoking a copy of f shall behave the same as invoking f.
and that this call can throw
any exceptions thrown by the copy or move constructor of f, or std::bad_alloc if memory
for the internal data structures could not be allocated.
This implicitly implies that the type F must be at least MoveConstructible, or CopyConstructible, if an lvalue reference is handed to the function.
Hence, it's not a bug, it's just not specified that precisely. To solve the problem of putting a std::packaged_task<int()> into a std::packaged_task<void()> just wrap the first into a shared_ptr like this:
#include <future>
#include <memory>
int main()
{
auto intTask = std::make_shared<std::packaged_task<int()>>(
[]()->int{ return 5; } );
std::packaged_task<void()> voidTask{ [=]{ (*intTask)(); } };
}
The purpose is to execute CVS890Executor::do_full_frame when calling the m_callback_fn within CDevVS890.
Following is the incriminated code:
"CDevVS890.h"
typedef std::tr1::function<void (void* frame, int len)> DoFrameFn;
class CDevVS890
{
public:
CDevVS890();
void receive();
DoFrameFn m_callback_fn;
}
"CDevVS890.cpp"
void CDevVS890::receive()
{
...
m_callback_fn((void*)frame, (int)len);
}
/*----------------------------------------------------------------------*/
"CVS890Executor.h"
class CVS890Executor
{
public:
CVS890Executor();
private:
void hookup_to_DevVS890();
void do_full_frame( void* frame, int len );
}
"CVS890Executor.cpp"
CVS890Executor::CVS890Executor()
{
hookup_to_DevVS890();
}
void CVS890Executor::hookup_to_DevVS890()
{
m_pDevVS890 = new CDevVS890();
m_pDevVS890->m_callback_fn =
std::tr1::bind(&CVS890Executor::do_full_frame, this, _1);
}
void CVS890Executor::do_full_frame(void* frame, int len)
{
...
}
The errors are multiple and very difficult to read:
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1/functional:56,
from ../../src/Common/CDevVS890.h:17,
from CVS890Executor.h:13,
from CVS890Executor.cpp:8:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional: In member function âtypename std::tr1::result_of<_Functor(typename std::tr1::result_of 0)>(_Bound_args, std::tr1::tuple<_UElements ...>)>::type ...)>::type std::tr1::_Bind<_Functor(_Bound_args ...)>::__call(const std::tr1::tuple<_UElements ...>&, std::tr1::_Index_tuple<_Indexes ...>) [with _Args = void*&, int&, int ..._Indexes = 0, 1, _Functor = std::tr1::_Mem_fn, _Bound_args = CVS890Executor*, std::tr1::_Placeholder<1>]â:
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1191: instantiated from âtypename std::tr1::result_of<_Functor(typename std::tr1::result_of 0)>(_Bound_args, std::tr1::tuple<_UElements ...>)>::type ...)>::type std::tr1::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) [with _Args = void*, int, _Functor = std::tr1::_Mem_fn, _Bound_args = CVS890Executor*, std::tr1::_Placeholder<1>]â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1668: instantiated from âstatic void std::tr1::_Function_handler::_M_invoke(const std::tr1::_Any_data&, _ArgTypes ...) [with _Functor = std::tr1::_Bind(CVS890Executor*, std::tr1::_Placeholder<1>)>, _ArgTypes = void*, int]â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:2005: instantiated from âstd::tr1::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(_ArgTypes ...)>::Useless>::_type) [with _Functor = std::tr1::_Bind(CVS890Executor*, std::tr1::_Placeholder<1>)>, _Res = void, _ArgTypes = void*, int]â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1885: instantiated from âtypename __gnu_cxx::__enable_if<(! std::tr1::is_integral::value), std::tr1::function<_Res(ArgTypes ...)>&>::_type std::tr1::function<_Res(_ArgTypes ...)>::operator=(_Functor) [with _Functor = std::tr1::_Bind(CVS890Executor*, std::tr1::_Placeholder<1>)>, _Res = void, _ArgTypes = void*, int]â
CVS890Executor.cpp:115: instantiated from here
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1137: error: no match for call to â(std::tr1::_Mem_fn) (CVS890Executor*&, void*&)â
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:546: note: candidates are: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class&, _ArgTypes ...) const [with _Res = void, _Class = CVS890Executor, _ArgTypes = void*, int]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:551: note: _Res std::tr1::_Mem_fn<_Res (_Class::*)(_ArgTypes ...)>::operator()(_Class*, _ArgTypes ...) const [with _Res = void, _Class = CVS890Executor, _ArgTypes = void*, int]
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/tr1_impl/functional:1137: error: return-statement with a value, in function returning 'void'
make: * [CVS890Executor.o] Error 1
Any idea what's wrong with this?
Cheers
You forgot about the second argument. Your call of bind function should be like this:
std::tr1::bind(&CVS890Executor::do_full_frame, this, _1, _2);
// ^^
In CVS890Executor::hookup_to_DevVS890(), you are not binding any arguments to the member function do_full_frame.
You are also trying to assign the return value of the function to m_callback_fn but do_full_frame() is declared to return void (no return value).