Compile errors using std::bind in gcc 4.7
I am having a lot of trouble using std::bind
in various places of my code. Sometimes it works, sometimes it doesn't, so I assume I am doing something fundamentally wrong.
As far as I understand, the following basic use of std::bind
should work fine:
#include <functional>
int foo(int a, int b){ return a+b; }
int main(){
using namespace std::placeholders;
// works
auto bar_auto=std::bind(foo,1,_2);
// compile error
std::function<int(int)> bar_fun=std::bind(foo,1,_2);
int quux=1;
// compile error
std::function<int(int)> bar_fun_lvalue=std::bind(foo,quux,_2);
}
Surely the type of bar_auto
is std::function<int(int)>
(type of foo
with 1 int
argument bound), so why does bar_fun
fail to compile? I included bar_fun_lvalue
because some googling showed me that rvalues used to be problematic. but this didn't fix anything.
It resembles this bug, but that's so old I don't expect it to be relevant.
gcc's output is not particularly enlightening:
In file included from bindnew.cpp:1:0: /usr/include/c++/4.7/functional: In instantiation of 'static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = int; _Functor = std::_Bind))(int, int)>; _ArgTypes = {int}]': /usr/include/c++/4.7/functional:2298:6: required 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))(int, int)>; _Res = int; _ArgTypes = {int}; typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function::_Useless]' bindnew.cpp:15:52: required from here /usr/include/c++/4.7/functional:1912:40: error: no match for call to '(std::_Bind))(int, int)>) (int)' /usr/include/c++/4.7/functional:1140:11: note: candidates are: /usr/include/c++/4.7/functional:1211:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1211:2: note:
template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1206:35: error: cannot convert 'std::_No_tuple_element' to 'int' in argument passing /usr/include/c++/4.7/functional:1225:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1225:2: note:
template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1219:35: error: cannot convert 'std::_No_tuple_element' to 'int' in argument passing /usr/include/c++/4.7/functional:1239:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1239:2: note:
template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1233:35: error: cannot convert 'std::_No_tuple_element' to 'int' in argument passing /usr/include/c++/4.7/functional:1253:2: note: template _Result std::_Bind<_Functor(_Bound_args ...)>::operator()(_Args&& ...) const volatile [with _Args = {_Args ...}; _Result = _Result; _Functor = int (*)(int, int); _Bound_args = {int, std::_Placeholder<2>}] /usr/include/c++/4.7/functional:1253:2: note: template argument deduction/substitution failed: /usr/include/c++/4.7/functional:1247:35: error: cannot convert 'std::_No_tuple_element' to 'int' in argument passing
The placeholder position objects (eg when you use _2
) is not the position of the argument in the function you call, but a placeholder for the argument in the created callable object. Instead always start with _1
and increase.
So:
auto bar_auto=std::bind(foo,1,_1);
etc.
This means you can switch the arguments in the object created by std::bind
by simply doing like
auto bar_auto=std::bind(foo,_2,_1);
When you "call" the bar_auto
object, the first argument will be the second argument to foo
, and the second argument in the call will be the first argument to foo
.
The _2
placeholder means to use second argument of the returned functor. Therefore the type of
std::bind(foo,1,_2)
is not std::function<int(int)>
but
std::function<int(unspecified_type, int)>
To get std::function<int(int)>
, use
std::bind(foo, 1, _1)
// ^^
链接地址: http://www.djcxy.com/p/29752.html