Programmierung calling C++ bind-bound functions with variable parameters
/*
Consider this following small example program.
*/
#include <functional>
#include <iostream>
using namespace std::placeholders;
/*
We write a subroutine that outputs the multiple of its arguments, a and b.
*/
void multiple(int a, int b, const std::string & who) {
std::cout << who << ":\t" << a << "×" << b << "=" << a*b << std::endl;
}
int main() {
/*
We then call it from main.
*/
multiple(2,3,"direct");
/*
Next, we want to use bind to bind some arguments and call it. Unsurprisingly, the output is the same.
*/
std::bind(multiple,2,3,"bind")();
/*
We can also store this bound function and call it:
*/
auto bound(std::bind(multiple,2,3,"bound"));
bound();
/*
Things get wicked, when we want to predefine only one parameter, though :(
*/
//std::bind(multiple,2,_1,"bindp")(3); // you wish!
/*
That’s what my distribution’s latest GNU C++ compiler thinks about our try…
% g++-4.5 -Wall -pedantic -ansi -std=c++0x bind.cpp
bind.cpp: In function ‘int main()’:
bind.cpp:39:37: error: no match for call to ‘(std::_Bind<void (*(int, std::_Placeholder<1>, const char*))(int, int, const std::basic_string<char>&)>) (int)’
/usr/include/c++/4.5/tr1_impl/functional:1189: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, int, const std::basic_string<char>&), _Bound_args = int, std::_Placeholder<1>, const char*, typename std::result_of<_Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void]
/usr/include/c++/4.5/tr1_impl/functional:1200: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, int, const std::basic_string<char>&), _Bound_args = int, std::_Placeholder<1>, const char*, typename std::result_of<const _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void]
/usr/include/c++/4.5/tr1_impl/functional:1212: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, int, const std::basic_string<char>&), _Bound_args = int, std::_Placeholder<1>, const char*, typename std::result_of<volatile _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void]
/usr/include/c++/4.5/tr1_impl/functional:1225: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, int, const std::basic_string<char>&), _Bound_args = int, std::_Placeholder<1>, const char*, typename std::result_of<const volatile _Functor(typename std::result_of<std::_Mu<_Bound_args>(_Bound_args, std::tuple<_UElements ...>)>::type ...)>::type = void]
much like the one before:
% g++-4.4 -Wall -pedantic -ansi -std=c++0x bind.cpp
bind.cpp: In function ‘int main()’:
bind.cpp:39: error: no match for call to ‘(std::_Bind<void (*(int, std::_Placeholder<1>, const char*))(int, int, const std::string&)>) (int)’
/usr/include/c++/4.4/tr1_impl/functional:1189: note: candidates are: 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 = int, _Functor = void (*)(int, int, const std::string&), _Bound_args = int, std::_Placeholder<1>, const char*]
/usr/include/c++/4.4/tr1_impl/functional:1200: note: typename std::result_of<const _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& ...) const [with _Args = int, _Functor = void (*)(int, int, const std::string&), _Bound_args = int, std::_Placeholder<1>, const char*]
/usr/include/c++/4.4/tr1_impl/functional:1212: note: typename std::result_of<volatile _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& ...) volatile [with _Args = int, _Functor = void (*)(int, int, const std::string&), _Bound_args = int, std::_Placeholder<1>, const char*]
/usr/include/c++/4.4/tr1_impl/functional:1225: note: typename std::result_of<const volatile _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& ...) const volatile [with _Args = int, _Functor = void (*)(int, int, const std::string&), _Bound_args = int, std::_Placeholder<1>, const char*]
Not quite sure whether this is the expected behaviour.
Note that we can still store the result; doesn’t mean that we could call it though:
*/
auto boundp(std::bind(multiple,2,_1,"boundp"));
//boundp(3); // you wish!
/*
Our best bet is to fix the bind-expression to a function-type:
*/
static_cast<std::function<void(int)>>(std::bind(multiple,2,_1,"funs"))(3);
/*
Or just store it away, works nicely as well.
*/
std::function<void(int)> funv(std::bind(multiple,2,_1,"funv"));
funv(3);
/*
(This solution did not work here with GNU C++ 4.5.0 20090925 (experimental) [trunk revision 152168], which garbles up the string parameter.)
*/
return 0;
}