boost::bind, boost::function & placeholders flexibility
Hello everybody, First of all, i'm a beginner trying to understand the use of the boost::bind library. Here is my problem : I'd like to know if there is a way to omit placeholders when calling boost::bind and let the compiler deduce their number. I understand that this is contrary to the flexibility offers by the placeholder, but i need to do something like that. void bar() {} void bar2(int) {} // Compile and works well boost::function < void ()> f1( boost::bind(&bar) ) ; boost::function < void (int) > f2( boost::bind(&bar2,_1) ) ; // i'd like to write this, but it doesn't compile // without the placeholders boost::function < void (int) > f2( boost::bind(&bar2) ) ; // i can write a small helper function mybind to achieve my goal // this compile and works well mybind(bar2) ; with template <typename Ret, typename Arg1, typename Arg2> void mybind(Ret (*Func)(Arg1, Arg2)) { boost::function<Ret (Arg1, Arg2)> f(Func) ; } I hope you understand what i've try to show. Maybe i missed something in the documentation. Thank you for reading ! Here is the working .cpp file i use to test things. =============================== #include <iostream> #include <stdexcept> #include <boost/bind.hpp> #include <boost/function.hpp> template <typename Ret, typename Arg1, typename Arg2> void mybind(Ret (*Func)(Arg1)) { boost::function<Ret (Arg1)> f(Func) ; } void bar() { std::cout << "bar()\n" ; } void bar2(int a) { std::cout << "bar2(int)\n" ; } int main (int argc, char* argv[]) { try { // Compile and works well { boost::function < void ()> f1( boost::bind(&bar) ) ; boost::function < void (int) > f2( boost::bind(&bar2,_1) ) ; } /* // i'd like to write this, but it doesn't compile { // without the placeholders boost::function < void (int) > f2( boost::bind(&bar2) ) ; f2(5) ; } */ // i can write a small helper function mybind to achieve my goal // this compile and works well /* template <typename Ret, typename Arg1, typename Arg2> void mybind(Ret (*Func)(Arg1, Arg2)) { boost::function<Ret (Arg1, Arg2)> f(Func) ; } */ { mybind(bar2) ; } } catch(std::exception& e) { std::cout << e.what() << '\n' ; return -1 ; } catch(...) { std::cout << "Non standard exception\n" ; return -1 ; } } ========================================
jbd wrote:
Hello everybody,
First of all, i'm a beginner trying to understand the use of the boost::bind library. Here is my problem :
I'd like to know if there is a way to omit placeholders when calling boost::bind and let the compiler deduce their number. I understand that this is contrary to the flexibility offers by the placeholder, but i need to do something like that.
Why do you _need_ to do that? As far as I'm aware, it's not possible to use bind without the placeholders, but I don't really see why it would be necessary. Sebastian Redl
Ok, thank you responding me ! My example was just here as "proof" of what i need. My idea is to encapsulate a boost::function of any type in a template class, which herite from a pure virtual class FooVirtual. My goal is to transform any function into a FooVirtual* using an helper function. I realize my last message was not very clear, here is a better example #include <iostream> #include <stdexcept> #include <boost/bind.hpp> #include <boost/function.hpp> template <typename Ret, typename Arg1> boost::function<Ret (Arg1)> mybind(Ret (*Func)(Arg1)) { boost::function<Ret (Arg1)> f(Func) ; return f ; } void bar() {} void bar2(int a) {} int main (int argc, char* argv[]) { try { boost::function < void ()> f1( boost::bind(&bar) ) ; boost::function < void (int) > f2( boost::bind(&bar2,_1) ) ; // doesn't work : // boost::function < void (int) > f2( boost::bind(&bar2) ) ; // this is ok boost::function < void (int) > f3( mybind(&bar2) ) ; } catch(std::exception& e) { std::cout << e.what() << '\n' ; return -1 ; } catch(...) { std::cout << "Non standard exception\n" ; return -1 ; } }
jbd wrote:
template <typename Ret, typename Arg1> boost::function<Ret (Arg1)> mybind(Ret (*Func)(Arg1)) { boost::function<Ret (Arg1)> f(Func) ; return f ; }
[...]
// doesn't work : // boost::function < void (int) > f2( boost::bind(&bar2) ) ;
// this is ok boost::function < void (int) > f3( mybind(&bar2) ) ;
It isn't clear why do you need to bind bar2 at all, instead of just using boost::function < void (int) > f3( &bar2 ) ;
Hello,
Peter Dimov wrote: It isn't clear why do you need to bind bar2 at all, instead of just using boost::function < void (int) > f3( &bar2 ) ;
To make a long story short, i'd like people always use the same mecanism (syntax), not a boost::bind here and nothing there. Maybe I tried to simplify my problem too much. The small code i'm "working" on is at the end of this message. I will try to say what i really want to do with words. The idea : class FunctionInterface : -> a pure virtual classe with an public void execute(const std::string&) = 0 member class GeneralFunctor : -> a class with a boost::shared_ptr<FunctionInterface> function_ member which is called via the operator()(const std::string) const ; The constructor take a pointer to a FunctionInterface. template < typename Func > class Functor : public FunctionInterface -> keeps a boost::function<Func> as a member and implement the execute function template < typename FuncType > GeneralFunctor MakeFunctor(FuncType func) -> This is my helper function to build a GeneralFunctor from any boost::function Here is some example : GeneralFunctor f1( MakeFunctor( boost::bind(&bar) ) ) ; GeneralFunctor f2( MakeFunctor( boost::bind(&bar2,_1) ) ) ; But i'd like to write for the convenience of the user and save some typing : GeneralFunctor f2( MakeFunctor( boost::bind(&bar2) ) ) ; But why do i need to use boost::bind here ? Why not directy a boost::function like you suggest to me ? Something like GeneralFunctor f3( MakeFunctor( boost::function<void (int)>(&bar2) ) ) ; As i said, i don't want people (me ;)) asking themself what they should do in this or this situation. That's why i introduce my helper function, mybind, which i can use like that : template <typename Ret, typename Arg1> boost::function<Ret (Arg1)> mybind(Ret (*Func)(Arg1)) { boost::function<Ret (Arg1)> f(Func) ; return f ; } GeneralFunctor f4( MakeFunctor( mybind(bar2) ) ) ; I really can always call MakeFunctor with a boost::function directly, something like MakeFunctor( boost::function<void (int)>(&bar2) ) But my purpose is just to make my life easier by using a uniform way letting boost::bind, or a plenty of overloaded mybind function, doing all the work :D I'd like not to fill the boost::function template parameters myself each time. My message is certainly quite confuse, i'm sorry for that but it certainly show that i don't know well the subject ... and the english language =) Thank you anyway. =========================== #include <iostream> #include <string> #include <stdexcept> #include <boost/smart_ptr.hpp> #include <boost/bind.hpp> #include <boost/function.hpp> class FunctionInterface { public: typedef boost::shared_ptr<FunctionInterface> pointer ; virtual ~FunctionInterface() {} virtual std::string execute(const std::string& params="") const = 0 ; } ; template < typename Func > class Functor : public FunctionInterface { private: typedef Func func_type ; func_type func_ ; public: Functor(Func f) : func_(f) {} std::string execute(const std::string& params="") const { return "" ; } } ; class GeneralFunctor { public: GeneralFunctor(const FunctionInterface::pointer func) : function_(func) {} std::string operator ()(const std::string& params = "") const { if ( !function_ ) throw "Error calling null function pointer" ; return function_->execute(params) ; } private: boost::shared_ptr<FunctionInterface> function_ ; } ; template < typename FuncType > GeneralFunctor MakeFunctor(FuncType func) { FunctionInterface::pointer ptr(new Functor<FuncType>(func)) ; return GeneralFunctor(ptr) ; } template <typename Ret, typename Arg1> boost::function<Ret (Arg1)> mybind(Ret (*Func)(Arg1)) { boost::function<Ret (Arg1)> f(Func) ; return f ; } void bar() {} void bar2(int a) {} int main (int argc, char* argv[]) { try { GeneralFunctor f1( MakeFunctor( boost::bind(&bar) ) ) ; GeneralFunctor f2( MakeFunctor( boost::bind(&bar2,_1) ) ) ; GeneralFunctor f3( MakeFunctor( boost::function<void (int)>(&bar2) ) ) ; GeneralFunctor f4( MakeFunctor( mybind(bar2) ) ) ; } catch(std::exception& e) { std::cout << e.what() << '\n' ; return -1 ; } catch(...) { std::cout << "Non standard exception\n" ; return -1 ; } } =========================== Le Fri, 12 May 2006 22:18:57 +0300, Peter Dimov a écrit :
jbd wrote:
template <typename Ret, typename Arg1> boost::function<Ret (Arg1)> mybind(Ret (*Func)(Arg1)) { boost::function<Ret (Arg1)> f(Func) ; return f ; }
[...]
// doesn't work : // boost::function < void (int) > f2( boost::bind(&bar2) ) ;
// this is ok boost::function < void (int) > f3( mybind(&bar2) ) ;
It isn't clear why do you need to bind bar2 at all, instead of just using
boost::function < void (int) > f3( &bar2 ) ;
"jbd" <evadream.mlist@evadream.net> wrote
Peter Dimov wrote: It isn't clear why do you need to bind bar2 at all, instead of just using boost::function < void (int) > f3( &bar2 ) ;
To make a long story short, i'd like people always use the same mecanism (syntax), not a boost::bind here and nothing there.
I would disagree with this approach. First it introduces unnecessary runtime and compile time performance overhead. More importantly, as great as boost::bind is, it is just a mechanism for making function objects. There are other mechanisms, like, for example, STL binders and adapters, boost::lambda or writing your own function object. A function pointer can be used directly, since function objects are modeled after it in the first place. Using boost::bind when it is not required might produce the code that is more difficult to understand and maintain. Regards, Arkadiy
I see your point and i agree with you. My goal is not to build a "pattern" i will use everyday. I'm just learning, testing things =) Thank you for your response ! Le Fri, 12 May 2006 17:46:04 -0400, Arkadiy Vertleyb a écrit :
"jbd" <evadream.mlist@evadream.net> wrote
Peter Dimov wrote: It isn't clear why do you need to bind bar2 at all, instead of just using boost::function < void (int) > f3( &bar2 ) ;
To make a long story short, i'd like people always use the same mecanism (syntax), not a boost::bind here and nothing there.
I would disagree with this approach. First it introduces unnecessary runtime and compile time performance overhead. More importantly, as great as boost::bind is, it is just a mechanism for making function objects. There are other mechanisms, like, for example, STL binders and adapters, boost::lambda or writing your own function object. A function pointer can be used directly, since function objects are modeled after it in the first place.
Using boost::bind when it is not required might produce the code that is more difficult to understand and maintain.
Regards, Arkadiy
jbd <evadream.mlist@evadream.net> writes:
Hello,
Peter Dimov wrote: It isn't clear why do you need to bind bar2 at all, instead of just using boost::function < void (int) > f3( &bar2 ) ;
To make a long story short, i'd like people always use the same mecanism (syntax), not a boost::bind here and nothing there.
Maybe I tried to simplify my problem too much. The small code i'm "working" on is at the end of this message. I will try to say what i really want to do with words.
The idea :
class FunctionInterface : -> a pure virtual classe with an public void execute(const std::string&) = 0 member
class GeneralFunctor : -> a class with a boost::shared_ptr<FunctionInterface> function_ member which is called via the operator()(const std::string) const ; The constructor take a pointer to a FunctionInterface.
template < typename Func > class Functor : public FunctionInterface -> keeps a boost::function<Func> as a member and implement the execute function
template < typename FuncType > GeneralFunctor MakeFunctor(FuncType func) -> This is my helper function to build a GeneralFunctor from any boost::function
At first glance this looks like a very complicated and expensive way of adding an OO layer over boost::function, which is *already* providing all the dynamic polymorphism you need. I could be missing something, but maybe you just need to get comfortable with using boost::function and operator() instead of GeneralFunctor and execute()? FWIW, there's a reason we do this stuff with operator(): it improves interoperability (e.g. with STL). HTH, -- Dave Abrahams Boost Consulting www.boost-consulting.com
Thank you for those pertinents remarks, i agree perfectly. I just want to train myself by investigating things. My wish is not to invent something i'm gonna be using everyday, only in my 100 lines main.cpp files ;)
At first glance this looks like a very complicated and expensive way of adding an OO layer over boost::function, which is *already* providing all the dynamic polymorphism you need. I could be missing something, but maybe you just need to get comfortable with using boost::function and operator() instead of GeneralFunctor and execute()? FWIW, there's a reason we do this stuff with operator(): it improves interoperability (e.g. with STL).
HTH,
participants (5)
-
Arkadiy Vertleyb
-
David Abrahams
-
jbd
-
Peter Dimov
-
Sebastian Redl