The following code compiles fine with GCC 4.3.3 and 4.4.2, but fails to compile with 4.5 (snapshot from 2009-12-31): #include <functional> void f( int ) {} int main() { std::function< void( int ) > pf = std::bind( &f, std::placeholders::_1 ); } with the following error: In file included from t.cc:1:0: /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional: In static member function ‘static void std::_Function_handler<void(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Functor = std::_Bind<void (*(std::_Placeholder<1>))(int)>, _ArgTypes = {int}]’: /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional:2127:6: instantiated from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename __gnu_cxx::__enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::__type) [with _Functor = std::_Bind<void (*(std::_Placeholder<1>))(int)>, _Res = void, _ArgTypes = {int}, typename __gnu_cxx::__enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::__type = std::function<void(int)>::_Useless]’ t.cc:3:85: instantiated from here /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional:1748:9: error: no match for call to ‘(std::_Bind<void (*(std::_Placeholder<1>))(int)>) (int)’ /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional:1219:9: note: candidates are: typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) [with _Args = {int}, _Functor = void (*)(int), _Bound_args = {std::_Placeholder<1>}, typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void] /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional:1230:9: note: typename std::result_of<const _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) const [with _Args = {int}, _Functor = void (*)(int), _Bound_args = {std::_Placeholder<1>}, typename std::result_of<const _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void] /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional:1242:9: note: typename std::result_of<volatile _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) volatile [with _Args = {int}, _Functor = void (*)(int), _Bound_args = {std::_Placeholder<1>}, typename std::result_of<volatile _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void] /home/frey/work/install/gcc-4.5-snapshot/lib/gcc/x86_64-unknown-linux-gnu/4.5.0/../../../../include/c++/4.5.0/functional:1255:9: note: typename std::result_of<const volatile _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args& ...) const volatile [with _Args = {int}, _Functor = void (*)(int), _Bound_args = {std::_Placeholder<1>}, typename std::result_of<const volatile _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void]
Thanks Daniel. Jon, can you have a look? I verified that the tr1 code we were using in 4.4.x and before is fine, thus should be either the std::function changes vs rvalue references or, less likely I believe, the void special case changes.
Thanks.
From a quick look, I think the problem is that std::function now uses perfect forwarding, but std::bind doesn't yet. So invoking the function passes an rvalue to _Bind::operator() which fails to bind to _Args& Previously, std::function took its arguments by value, and _Bind::operator()(_Args&...) bound an lvalue reference to that by-value parameter: return _M_invoker(_M_functor, __args...); Now it does this: return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...); and so the rvalue cannot bind to _Args& This will be fixed when std::bind supports rvalue references. I was going to finish those changes after updating <future>, but I have been delayed by some unexpected events and am away from my home PC which contains my work in progress.
Ok, Jon, thanks. At some point, however, *soon* I'm afraid given the gcc4.5 schedule, we'll have to make a tough choice: if updating only std::function leads to bad regressions in common usages of std::bind, and the latter isn't ready in time for gcc4.5 for whatever reason, we can't ship something half halfway through, I think...
Jon, I'm raising Priority and Severity not because the isssue per se is that deadly serious (after all the whole C++0x is experimental, nothing should be really critical about it), but because we want to make sure we don't forget when (soon) we'll branch and will be in Stage 4, close to the release, and we'll have to make the final decisions about <functional>.
ok, understood - I'm looking at finishing the bind changes at the moment
Let's keep a P1 for now, we really don't want to forget.
Created attachment 19453 [details] preliminary patch I'm testing this, which is not ready for checkin, but updates std::bind to handle rvalues and fixes this bug. As well as fixing the affected testcases (done but not included in this patch) and fixing the formatting, the decaying behaviour from the resolution to LWG 817 needs to be implemented: http://home.roadrunner.com/~hinnant/issue_review/lwg-active.html#817 I *think* the patch is correct, but testsuite/30_threads/call_once/39909.cc fails due to a front-end bug: /home/redi/src/gcc/build/x86_64-unknown-linux-gnu/libstdc++-v3/include/functional:1179:67: sorry, unimplemented: unable to determine the declared type of expression 'declval<std::reference_wrapper<Inc> >()()' A workaround for this is to change call_once to use bind<void>() instead of bind() i.e. Index: include/std/mutex =================================================================== --- include/std/mutex (revision 155587) +++ include/std/mutex (working copy) @@ -722,12 +722,12 @@ namespace std call_once(once_flag& __once, _Callable __f, _Args&&... __args) { #ifdef _GLIBCXX_HAVE_TLS - auto __bound_functor = std::bind(__f, __args...); + auto __bound_functor = std::bind<void>(__f, __args...), __once_callable = &__bound_functor; __once_call = &__once_call_impl<decltype(__bound_functor)>; #else unique_lock<mutex> __functor_lock(__get_once_mutex()); - __once_functor = std::bind(__f, __args...); + __once_functor = std::bind<void>(__f, __args...); __set_once_functor_lock_ptr(&__functor_lock); #endif (the ability to use this workaround was the main reason I fixed std::bind<void> recently)
Great. Let's go ahead this way, then!
OK P.S. (In reply to comment #8) > > (the ability to use this workaround was the main reason I fixed std::bind<void> > recently) I think I've mentioned to Paolo in private mail that we could use bind<R> (specifically, bind<void>) in several places because doing so should reduce compile time, as it avoids using result_of and decltype to determine the return type. I haven't done so yet, because deducing the return type provides better testcases for std::bind while I'm still working on it. Once the work is complete, we should consider using bind<R> in <mutex> and <future>
By the way, Jon, I don't think we should delay committing this work only because of DR 817, after all isn't even Ready...
... if we have something rather satisfactory wrt all the other isses / testcases we are aware of in this area the sooner we commit the code, the better: I'm sure that Daniel can help testing it further on his code base: worst case, if after the branch point things look really bad, we revert the whole package for the release, luckily we are not talking about tons of code intertwined with the rest of the library. Only, we have to keep the eyes open the next few weeks. We can make it ;)
Created attachment 19458 [details] updated patch this fixes the formatting in the previous patch, includes the call_once workaround, and updates the testsuite. This patch disables the volatile-qualified _Bind::operator() overloads with '#if 0' because I'm not smart enough to figure out how to support that. If those overloads are enabled then you get errors when trying to pass reference_wrapper or _Bind as an argument to _Bind::operator(). IMHO we can live without volatile support for 4.5 because I don't think it's a widely-used feature. As well as this bug, it fixes bug 35569 and its dup I want to do some more tests to be sure this is ready
For sure Jon the code is very, very clean, excellent.
Jon, what do you think, shall we go ahead?
Let's go for it, I check it in later today
Subject: Bug 42593 Author: redi Date: Tue Jan 12 00:53:30 2010 New Revision: 155826 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=155826 Log: 2010-01-12 Jonathan Wakely <jwakely.gcc@gmail.com> PR libstdc++/24803 PR libstdc++/35569 PR libstdc++/42593 * include/std/functional (bind): Forward rvalues and detect correct result type of bound function object. * include/std/mutex (call_once): Specify bind result type. * testsuite/20_util/reference_wrapper/invoke.cc: Remove invalid tests. * testsuite/20_util/reference_wrapper/24803.cc: Remove invalid tests and enable FIXME tests. * testsuite/20_util/bind/35569.cc: New. * testsuite/20_util/bind/ref2.cc: New. * testsuite/20_util/bind/38889.cc: New. * testsuite/20_util/bind/ref_neg.cc: New. * testsuite/20_util/bind/42593.cc: New. Added: trunk/libstdc++-v3/testsuite/20_util/bind/35569.cc trunk/libstdc++-v3/testsuite/20_util/bind/38889.cc trunk/libstdc++-v3/testsuite/20_util/bind/42593.cc trunk/libstdc++-v3/testsuite/20_util/bind/ref2.cc trunk/libstdc++-v3/testsuite/20_util/bind/ref_neg.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/std/functional trunk/libstdc++-v3/include/std/mutex trunk/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc trunk/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc
Fixed for 4.5.0