Search code examples
c++boostboost-function

How can I make boost::function not be so lenient?


typedef boost::function<void (int,bool)> MyCallback;
void RegisterCallback(MyCallback callback);

class A {
public:
    void GoodCallback(int intArg,bool boolArg) {
        printf("calling GoodCallback (%d,%s)\n",intArg,boolArg?"true":"false");
    }

    void BadCallback(int intArg) {
        printf("calling BadCallback (%d)\n",intArg);
    }
};

int TestFunction() {
    A * myA=new A();
    RegisterCallback(boost::bind(&A::GoodCallback,myA,_1,_2));

    RegisterCallback(boost::bind(&A::BadCallback,myA,_1));

    return 0;
}

Is there any way that I can make the second call to RegisterCallback not compile?

For context:
I recently changed the callback signature and added the bool argument. I thought I had updated everything that was using this, but I was mistaken. Other than renaming RegisterCallback everytime I change the signature, I would like to have a way to have the compiler enforce that all arguments are used.


Solution

  • I'm a bit late with this answer but since the problem is the binding you could do this step later with the help of a templated version for your callback registration function and another one for regular function pointers:

    template<typename C>
    void RegisterCallback(void (C::* func)(int, bool), C* inst)
    {
      MyCallback callback(boost::bind(func, inst, _1,_2));
    }
    
    void RegisterCallback(void (*func)(int, bool))
    {
      MyCallback callback(func);
    }
    
    A * myA = new A();     
    RegisterCallback(&A::GoodCallback, myA);      
    RegisterCallback(&A::BadCallback, myA); // DOES NOT COMPILE
    
    RegisterCallback(GoodCallback);
    RegisterCallback(BadCallback); // DOES NOT COMPILE
    

    This works as expected in VS2010 but has the disavantage of needing not one but two callback registration functions to correctly deal with member and non-member functions.

    As another option you might have a look at the boost function_types library. It provides a parameter_types metafunction that extracts the parameter types of function pointers and returns them as a MPL sequence. Then with a bit template magic it's possible to validate the parameters of the callback function, something like:

    #include <boost/function.hpp>
    #include <boost/bind.hpp>
    #include <boost/function_types/parameter_types.hpp>
    #include <boost/mpl/equal.hpp>
    
    using namespace boost;
    using namespace boost::function_types;
    
    template< typename Function >
    void RegisterCallback(Function f)
    {
       BOOST_MPL_ASSERT(( 
          mpl::equal< 
            parameter_types< Function >, 
            parameter_types< void(int,bool) >
          > 
       ));
    
       MyCallback callback(f);
    }
    
    template<typename Function, typename T>
    void RegisterCallback(Function f, T* inst)
    {
       BOOST_MPL_ASSERT(( 
         mpl::equal< 
           parameter_types< Function >, 
           parameter_types< void (T::*)(int,bool) >
         > 
       ));
    
       MyCallback callback(boost::bind(f, inst, _1, _2));  
    }
    

    This also works as expected in VS2010 but you still need two function declarations although it should be possible to pack them in one if you define them inside a struct (and use a default template parameter argument for T);