Boost :: bind with null function pointers

If the function pointer embedded in the boost::bind return object is NULL / nullptr / 0 , I need to take action other than calling it. How to determine if an object contains a null function pointer?

Addenda

  • I do not believe that I can use and compare boost::function , since the return object of boost::bind used with various call signatures in the template function.
  • A simplified example:
 template <typename BRO> Retval do_stuff(BRO func, enum Fallback fallback) { if (func == NULL) { return do_fallback(fallback); } else { return use_retval(func()); } } do_stuff(boost::bind(FuncPtrThatMightBeNull, var1, var2), fallback); 

Decision

Since the arity of the function does not change in the called call, I can "pass" the binding return object to boost::function and call .empty()

 Retval do_stuff(boost::function<Retval()> func, enum Fallback fallback) { if (func.empty()) return do_fallback(fallback); else return use_retval(func()); } 
+7
c ++ boost function-pointers bind boost-bind
source share
4 answers

You can either bind to a dummy function:

 void dummy() { /* has differing behaviour */ } // ... boost::bind(&dummy)(); 

... or, assuming you use Boost.Bind along with Boost.Function , return the constructed function object by default and check empty() before calling it:

 typedef boost::function<void (void)> F; F create() { return F(); } void use() { F f = create(); if(f.empty()) { /* ... */ } } 

Regarding the update:
I still donโ€™t see that there is a problem with binding to another function, such as the following:

 template <typename BRO> Retval do_stuff(BRO func) { return func(); } if(funcPtr) { do_stuff(boost::bind(&use_retval, boost::bind(funcPtr, a, b))); } else { do_stuff(boost::bind(&do_fallback, fallback)); } 

If you want to move this processing from the calling code, you can emulate the variational function of the template to support arities variables:

 template<class R, class T1> boost::function<R (T1)> bind_wrap(R (*fnPtr)(), T1& t1, Fallback fallback) { if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1)); else return boost::bind(&do_fallback, fallback); } template<class R, class T1, class T2> boost::function<R (T1, T2)> bind_wrap(R (*fnPtr)(T1, T2), T1& t1, T2& t2, Fallback fallback) { if(fnPtr) return boost::bind(&use_retval, boost::bind(funcPtr, t1, t2)); else return boost::bind(&do_fallback, fallback); } // ... etc. for all needed arities do_stuff(bind_wrap(funcPtr, var1, var2, fallback)); 

... or you use the approach described above to create boost::function<> objects or your own wrappers and check functor.empty() or similar in do_stuff() .

+5
source share

I would create a wrapper object to do this. Something like the following

 #include <boost/bind.hpp> #include <boost/function.hpp> #include <iostream> int aFunction(int i, int j) { std::cout<<"In a Function"<<std::endl; return i+j; } struct DefaultingFromFnPtr : public boost::function< int(int,int) > { explicit DefaultingFromFnPtr( int(*fn)(int,int) ) : fn_(fn) {} int operator()(int i, int j) const { if (fn_!=NULL) return fn_(i, j); return 7; } int(*fn_)(int,int); }; template<typename T> void do_stuff( T t ) { std::cout<<"RETURNED "<<t()<<std::endl; } int main( int argv, const char** argc) { int(*mightBeNullFnPtr)(int,int) = NULL; if( argv>1) { mightBeNullFnPtr = & aFunction; } int var1 = 10; int var2 = 20; do_stuff( boost::bind( DefaultingFromFnPtr( mightBeNullFnPtr ), var1, var2 ) ); } 

Compile this and run it with no arguments, and it will set mayBeNullFnPtr to NULL and call do_stuff with the wrapper class and therefore print it. 7. Run it with an argument and it will set the canByNullFnPtr parameter to aFunction and call do_stuff with this, print out 30.

If you want more general information, you will need to create a template for the DefaultingFromFnPtr class, but this should be fairly easy to do.

+1
source share

I am sure that calling boost :: bind with a null pointer (= creating a binding object) should be considered as undefined behavior, even if the failure only occurs when it is called.

0
source share

You will have to hack.

boost :: bind returns unspecified-nn. The only thing that can be done with these classes is the () operator. The only thing you know is that they are created for copying and have a typedef for result_type (which, by the way, means you don't need a template for the type of result).

You want something else - so you need to find the definition of unspecified-nn in boost (maybe several), hack them to have a member function is_null () that checks the conditions you want, and then calls it like your test .

This, of course, if you are sure that you will always receive a boost: bind'ed object in your template function. If someone tries to pass a pointer to a regular function, it will not compile. This will require the magic of the template.

-one
source share

All Articles