c++ std::bind universal reference can't compile - c++

#include <functional>
#include <iostream>
#include <type_traits>
using cb_t = std::function<void ()>;
template<typename CB_T, std::enable_if_t<std::is_constructible<cb_t, CB_T>::value, bool> = true>
void
on_my_write(int a, int b, CB_T&& cb) {
std::cout << "on_my_write:" << a << ", " << b << std::endl;
}
template<typename CB_T, std::enable_if_t<std::is_constructible<cb_t, CB_T>::value, bool> = true>
void foo(CB_T&& cb) {
auto b = std::bind(&on_my_write<CB_T>, std::placeholders::_1, std::placeholders::_2, std::forward<CB_T>(cb));
b(1, 2);
}
int main() {
foo([]{});
return 0;
}
compile this with command line
g++ ./try1.cpp -std=c++17
gave me:
./try1.cpp: In instantiation of ‘void foo(CB_T&&) [with CB_T = main()::<lambda()>; typename >std::enable_if<std::is_constructible<std::function<void()>, CB_T>::value, bool>::type <anonymous> = 1]’:
./try1.cpp:39:13: required from here
./try1.cpp:34:6: error: no match for call to ‘(std::_Bind<void (*(std::_Placeholder<1>, std::_Placeholder<2>, main()::<lambda()>))(int, int, main()::<lambda()>&&)>) (int, int)’
b(1, 2);
~^~~~~~
In file included from ./try1.cpp:19:0:
/usr/include/c++/7/functional:547:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int, int, main()::<lambda()>&&); _Bound_args = {std::_Placeholder<1>, std::_Placeholder<2>, main()::<lambda()>}]
operator()(_Args&&... __args)
^~~~~~~~
/usr/include/c++/7/functional:547:2: note: template argument deduction/substitution failed:
/usr/include/c++/7/functional:558:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int, int, main()::<lambda()>&&); _Bound_args = {std::_Placeholder<1>, std::_Placeholder<2>, main()::<lambda()>}]
operator()(_Args&&... __args) const
^~~~~~~~
/usr/include/c++/7/functional:558:2: note: template argument deduction/substitution failed:
/usr/include/c++/7/functional:576:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int, int, main()::<lambda()>&&); _Bound_args = {std::_Placeholder<1>, std::_Placeholder<2>, main()::<lambda()>}]
operator()(_Args&&... __args) volatile
^~~~~~~~
/usr/include/c++/7/functional:576:2: note: template argument deduction/substitution failed:
/usr/include/c++/7/functional:588:2: note: candidate: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = void (*)(int, int, main()::<lambda()>&&); _Bound_args = {std::_Placeholder<1>, std::_Placeholder<2>, main()::<lambda()>}]
operator()(_Args&&... __args) const volatile
^~~~~~~~
/usr/include/c++/7/functional:588:2: note: template argument deduction/substitution failed:
But if I change on_my_write(int a, int b, CB_T&& cb) to on_my_write(int a, int b, const CB_T& cb), then it will compile and run successfully.
I really don't understand why?
Could anybody explain this to me? thanks a lot!
I've tried several hours and can't figure it out.

Yes, this is slightly tricky. std::bind is of course not magical, it has to store the bound parameters somehow and it stores them as values by default, unless requested with std::ref argument.
Meaning that in the callstd::bind(...,std::forward<CB_T>(cb)), the cb is used to construct the bound member variable properly using the perfect forwarding.
But, the calling is not done with perfect forwarding sadly, the argument that bind will pass to on_my_write is always an l-value. It is not impossible to create std::bind version that would forward it and I do not know exactly why is it this way, but a good reason might be that such forwarding would make calling the bound functor multiple times dangerous.
So, since std::bind always passes the argument as l-value, you have a couple of options:
Remove perfect forwarding and use on_my_write(int a, int b, const CB_T& cb) as you did.
Remove perfect forwarding and move anyway, use on_my_write(int a, int b, CB_T& cb)
and use std::move(cb) inside to consume it. Be careful, this is exactly the case in which the new functor should be called just once.
Keep perfect forwarding but do not use it for this call which can be achieved by manually adding a reference:
std::bind(&on_my_write<CB_T&>, std::placeholders::_1, std::placeholders::_2,
std::forward<CB_T>(cb));
This will work thanks to reference collapsing rules and on_my_write(int a, int b, CB_T& cb) will be called always. You can still use 2. and move anyway.
Choose me Forget std::bind, use lambda:
template<typename CB_T, std::enable_if_t<std::is_constructible<cb_t, CB_T>::value,
bool> = true>
void foo(CB_T&& cb) {
auto b = [&cb](auto a,auto b){return on_my_write(a,b,std::forward<CB_T>(cb));};
b(1, 2);
}
This will forward cb properly, an extra advantage of this solution is that you do not have to deduce on_my_write manually.

Related

How to forward a mutable lambda

Here's a watered down example of the code I'm try to compile:
#include <iostream>
#include <functional>
template <class F>
auto foo(F&& fun)
{
return [callback = std::forward<F>(fun)](auto&&... args) {
std::invoke(callback, std::forward<decltype(args)>(args)...);
};
}
int main()
{
std::string cur("running"), target("ok");
foo([s1 = cur, s2 = target](std::string const& arg) /*mutable*/ {
if (s1 == arg)
{
std::cout << s1 << std::endl;
}
})("not ok");
return 0;
}
put simply I have a function foo that accepts callables, and is supposed to build a new callable from them. For the sake of the example, above I'm just invoking the fun argument but in the real case there are some decorations done to the callable and the result is placed into a data structure that invokes such "actions" under some conditions.
This example compiles and works just fine. The problem manifests when trying to pass mutable lambdas to foo. When I uncomment the mutable keyword above, I get this compilation error:
main.cpp: In instantiation of 'foo<main()::<lambda(const string&)> >(main()::<lambda(const string&)>&&)::<lambda(auto:1&& ...)> [with auto:1 = {const char (&)[7]}]':
main.cpp:21:7: required from here
main.cpp:8:20: error: no matching function for call to 'invoke(const main()::<lambda(const string&)>&, const char [7])'
8 | std::invoke(callback, std::forward<decltype(args)>(args)...);
| ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from main.cpp:2:
/usr/local/include/c++/11.2.0/functional:94:5: note: candidate: 'template<class _Callable, class ... _Args> std::invoke_result_t<_Callable, _Args ...> std::invoke(_Callable&&, _Args&& ...)'
94 | invoke(_Callable&& __fn, _Args&&... __args)
| ^~~~~~
/usr/local/include/c++/11.2.0/functional:94:5: note: template argument deduction/substitution failed:
In file included from /usr/local/include/c++/11.2.0/bits/move.h:57,
from /usr/local/include/c++/11.2.0/bits/nested_exception.h:40,
from /usr/local/include/c++/11.2.0/exception:148,
from /usr/local/include/c++/11.2.0/ios:39,
from /usr/local/include/c++/11.2.0/ostream:38,
from /usr/local/include/c++/11.2.0/iostream:39,
from main.cpp:1:
/usr/local/include/c++/11.2.0/type_traits: In substitution of 'template<class _Fn, class ... _Args> using invoke_result_t = typename std::invoke_result::type [with _Fn = const main()::<lambda(const string&)>&; _Args = {const char (&)[7]}]':
/usr/local/include/c++/11.2.0/functional:94:5: required by substitution of 'template<class _Callable, class ... _Args> std::invoke_result_t<_Callable, _Args ...> std::invoke(_Callable&&, _Args&& ...) [with _Callable = const main()::<lambda(const string&)>&; _Args = {const char (&)[7]}]'
main.cpp:8:20: required from 'foo<main()::<lambda(const string&)> >(main()::<lambda(const string&)>&&)::<lambda(auto:1&& ...)> [with auto:1 = {const char (&)[7]}]'
main.cpp:21:7: required from here
/usr/local/include/c++/11.2.0/type_traits:2933:11: error: no type named 'type' in 'struct std::invoke_result<const main()::<lambda(const string&)>&, const char (&)[7]>'
2933 | using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
| ^~~~~~~~~~~~~~~
Any idea why is that? Can my foo accept mutable lambdas as well?
Just add mutable to the lambda inside the foo:
template <class F>
auto foo(F&& fun)
{
return [callback = std::forward<F>(fun)](auto&&... args) mutable {
//^^^
std::invoke(callback, std::forward<decltype(args)>(args)...);
};
}

Is it possible to capture a variable number of parameters in a lambda?

Consider the following set of examples.
The function takeOnlyVoidFunction takes a function with zero arguments and simply executes it.
The function takeVariableArguments takes a variable number of arguments and executes the function using the arguments.
The function captureVariableArgs attempts to convert the second function into a lambda form that is acceptable by the first function, but it does not compile.
How can I make the function captureVariableArgs compile and exhibit the correct behavior of converting a function with a variable number of arguments into a closure with no arguments?
#include <stdio.h>
#include <functional>
void takeOnlyVoidFunction(std::function<void()> task) {
task();
}
template<typename _Callable, typename... _Args>
void takeVariableArguments(_Callable&& __f, _Args&&... __args) {
__f(__args...);
}
// How can I make this function compile?
template<typename _Callable, typename... _Args>
void captureVariableArgs(_Callable&& __f, _Args&&... __args) {
takeOnlyVoidFunction([=]() { __f(__args...);});
}
void normalFunction(int a, int b) {
printf("I am a normal function which takes params (%d,%d)\n", a, b);
}
int main() {
int a = 7;
int b = 8;
takeVariableArguments(normalFunction, a, b);
takeOnlyVoidFunction([=](){ normalFunction(a,b);});
captureVariableArgs(normalFunction, a, b);
}
I'm running gcc 4.9.2. Here is the compiler error I see.
g++ -std=c++11 Test.cc -o Test
Test.cc: In instantiation of ‘captureVariableArgs(_Callable&&, _Args&& ...)::<lambda()> [with _Callable = void (&)(int, int); _Args = {int&, int&}]’:
Test.cc:16:38: required from ‘struct captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>’
Test.cc:16:50: required from ‘void captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]’
Test.cc:28:45: required from here
Test.cc:16:34: error: variable ‘__f’ has function type
takeOnlyVoidFunction([=]() { __f(__args...);});
^
Test.cc:16:34: error: variable ‘__f’ has function type
Test.cc: In instantiation of ‘struct captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>’:
Test.cc:16:50: required from ‘void captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]’
Test.cc:28:45: required from here
Test.cc:16:34: error: field ‘captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>::<__f capture>’ invalidly declared function type
In file included from Test.cc:2:0:
/usr/include/c++/4.9/functional:2418:7: error: ‘std::function<_Res(_ArgTypes ...)>::function(_Functor) [with _Functor = captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>; <template-parameter-2-2> = void; _Res = void; _ArgTypes = {}]’, declared using local type ‘captureVariableArgs(_Callable&&, _Args&& ...) [with _Callable = void (&)(int, int); _Args = {int&, int&}]::<lambda()>’, is used but never defined [-fpermissive]
function<_Res(_ArgTypes...)>::
^
Update: A more minimal example demonstrating this problem.
#include <stdio.h>
// How can I make this function compile?
template<typename _Callable>
void captureVariableArgs(_Callable&& __f) {
takeOnlyVoidFunction( [=]{ __f(); } );
}
void normalFunction() {
printf("I am a normal function\n");
}
int main(){
captureVariableArgs(normalFunction);
}
As another potential workaround for GCC, instead of using a lambda, you could use std::bind:
template <typename F, typename... Args>
auto captureVariable(F&& f, Args&&... args)
{
return std::bind(std::forward<F>(f), std::forward<Args>(args)...);
}
This works for me under GCC 4.9.3.
The code in the post compiles fine with the latest clang&MSVC compilers but all the gccs refuse to compile it. So it seems a bug in gcc. Nevertheless, I found a way to make gcc happy: just don't use an "universal reference" on the callable argument, like this:
template<typename _Callable, typename... _Args>
int captureVariableArgs(_Callable _f, _Args&&... _args) {
return takeOnlyVoidFunction([=]() { _f(_args...);});
}
I can't explain why gcc doesn't accept your version, though. I'm not familiar with gcc-style error reporting and can't extract the true cause from the error message. But I think the workaround is ok since I don't see any value in "universal reference" in this case. In fact, I don't see why you use it on the args either.

Two-level bind fails on GCC/libstdc++ and Clang/libc++ [duplicate]

I'm having trouble in detecting why the heck is this not compiling. I've got some lambda function that returns a std::function based on some argument.
I've narrowed down my problem to this snippet(which doesn't use lambdas, but reproduces my error perfectly):
#include <functional>
#include <iostream>
struct foo {
template<class T>
void bar(T data) {
std::cout << data << "\n";
}
};
void some_fun(const std::function<void(int)> &f) {
f(12);
}
int main() {
foo x;
auto f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
auto w = std::bind(some_fun, f);
w();
}
The call to w() produces one of those lovely gcc error outputs in which I can't figure out what's going wrong. This is the error echoed by gcc 4.6.1:
g++ -std=c++0x test.cpp -o test
test.cpp: In function ‘int main()’:
test.cpp:20:7: error: no match for call to ‘(std::_Bind<void (*(std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>))(const std::function<void(int)>&)>) ()’
/usr/include/c++/4.6/functional:1130:11: note: candidates are:
/usr/include/c++/4.6/functional:1201:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1215:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1229:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
/usr/include/c++/4.6/functional:1243:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = void (*)(const std::function<void(int)>&), _Bound_args = {std::_Bind<std::_Mem_fn<void (foo::*)(int)>(foo, std::_Placeholder<1>)>}]
Here, f should be some callable object which takes an int as argument and calls x.bar(int) using it. On the other hand, w is just a callable object which calls some_fun(f), being f the callable object mentioned above, which has the signature expected by some_fun's parameter.
Am I missing something? I probably don't know how to actually mix std::bind and std::function.
std::bind expressions, like their boost::bind predecessors, support a type of composition operation. Your expression for w is roughly equivalent to
auto w=std::bind(some_fun, std::bind(&foo::bar<int>, x, std::placeholders::_1) );
Nesting binds in this manner is interpreted as
Calculate the value of x.bar<int>(y) where y is the first parameter passed into the resulting functor.
Pass that result into some_fun.
But x.bar<int>(y) returns void, not any function type. That's why this doesn't compile.
As K-ballo points out, with boost::bind, you can fix this problem with boost::protect. As Kerrek SB and ildjarn point out, one way around this issue is: don't use auto for f. You don't want f to have the type of a bind expression. If f has some other type, then std::bind won't attempt to apply the function composition rules. You might, for instance, give f the type std::function<void(int)>:
std::function<void(int)> f = std::bind(&foo::bar<int>, x, std::placeholders::_1);
auto w = std::bind(some_fun, f);
Since f doesn't literally have the type of a bind expression, std::is_bind_expression<>::value will be false on f's type, and so the std::bind expression in the second line will just pass the value on verbatim, rather than attempting to apply the function composition rules.
some_fun wants argument of type const std::function<void(int)> &.
std::bind returns "a function object of unspecified type T" (look at provided link, section "Return value"), that you are trying to pass as some_fun argument.
It seems this causes problem, because this argument type is not expected.
Look at: http://en.cppreference.com/w/cpp/utility/functional/bind

Does `std::packaged_task` need a CopyConstructible constructor argument?

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)(); } };
}

g++ std::bind error with shared_ptr

I'm having trouble understanding why the following code does not compile.
#include <memory>
#include <functional>
class Foo
{
public:
void Bar(int i) {}
};
void X(std::function<void(std::shared_ptr<Foo>)> f)
{
}
int main()
{
std::shared_ptr<Foo> f(new Foo);
auto f1(std::bind(&Foo::Bar, std::placeholders::_1, 1));
X(f1);
return 0;
}
g++ (4.6.3) outputs...
n file included from /usr/include/c++/4.6/memory:80:0,
from test.cpp:1:
/usr/include/c++/4.6/functional: In static member function ‘static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::_Bind<std::_Mem_fn<void (Foo::*)(int)>(std::_Placeholder<1>, int)>, _ArgTypes = {std::shared_ptr<Foo>}]’:
/usr/include/c++/4.6/functional:2148: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::_Bind<std::_Mem_fn<void (Foo::*)(int)>(std::_Placeholder<1>, int)>, _Res = void, _ArgTypes = {std::shared_ptr<Foo>}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<void(std::shared_ptr<Foo>)>::_Useless]’
test.cpp:19:7: instantiated from here
/usr/include/c++/4.6/functional:1778:2: error: no match for call to ‘(std::_Bind<std::_Mem_fn<void (Foo::*)(int)>(std::_Placeholder<1>, int)>) (std::shared_ptr<Foo>)’
/usr/include/c++/4.6/functional:1130:11: note: candidates are:
/usr/include/c++/4.6/functional:1201:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}, _Result = _Result, _Functor = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
/usr/include/c++/4.6/functional:1215:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}, _Result = _Result, _Functor = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
/usr/include/c++/4.6/functional:1229:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
/usr/include/c++/4.6/functional:1243:2: note: template<class ... _Args, class _Result> _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}, _Result = _Result, _Functor = std::_Mem_fn<void (Foo::*)(int)>, _Bound_args = {std::_Placeholder<1>, int}]
It's a GCC bug, which I fixed in 4.7, but I don't remember exactly which bug. I'll try to figure it out ...
Edit: Aha, it's PR 55463 so isn't fixed in 4.7, it's only fixed on GCC trunk (what will be 4.8)
The bug was that the call wrapper returned by mem_fn doesn't accept rvalues, and your std::function<void(std::shared_ptr<Foo>) type passes an rvalue shared_ptr<Foo> to the call wrapper return by bind.
As a workaround you can change your function signature to this:
void X(std::function<void(const std::shared_ptr<Foo>&)> f)
I don't think I can backport the fix to the 4.7 branch, because as a result of that bug I made some quite large changes to mem_fn that aren't really suitable for a stable release branch (I also found a new defect in the standard)