Search code examples
c++bindfunction-pointersboost-bindfunction-object

Binding the parameters before setting the function pointer?


I would like to try something out and unify some boilerplate code in one of our dynamic library API wrappers.

Essentially, I would like to do the following:

typedef bool (*MyFPtrT)(long id, std::string const& name);
typedef boost::function<bool (long id, std::string const& name)> MyFObjT;
...

...
  MyFPtrT pDllFun = NULL;
  long x = 42; string s = "Answer"; // API input, not hardcoded
  MyFObjT f = boost::bind(pDllFun, x, s);
  ...
  return Call(f);
...

template<FT>
bool Call(FT f) {
  ...
  MyFPtrT pDllFun = (MyFunPtr)::GetProcAddress(...);
  f.setFunctionPointerButLeaveBoundParameters(pDllFun); // <- how??
  // Now call the correctly rigged up function object:
  return f();
}

Is this possible? (With Boost or otherwise?) (C++03)


Solution

  • I don't think it can be done directly like that, because bind creates a new object that takes the function object and the arguments by reference, and you can't rebind references.

    However, you can easily enough write your own templated functor wrapper with a reassignable function pointer:

    template <typename R, typename A, typename B>
    struct ReAssFunctor
    {
      typedef R(*FP)(A, B);
    
      ReAssFunctor(const A & a_, const B & b_) a(a_), b(b_) { }
    
      R operator()() const { return func(a, b); }
    
      FP function;
    
    private:
      const A & a;
      const B & b;
    };
    

    [Edit:] Do check the comments below; holding references taken by const reference in the constructor can be dangerously abused, so be careful, or save a and b by value if you prefer.[/]

    Now you can initialize the functor with the arguments early:

    ReAssFunctor<R, A, B> raf(a, b);
    

    Then assign a function pointer and call:

    raf.function = foo;
    raf();
    
    raf.function = goo;
    raf();
    

    You could even replace the call operator by this:

      template <typename U>
      U operator()(U (f*)(A, B)) const { return f(a, b); }
    

    And then invoke the functor with the function pointer as the argument:

    raf(fp1);  // calls fp1(a,b);
    raf(fp2);  // calls fp2(a,b);
    

    In that case you don't need the return type as a fixed parameter any longer, but now you don't get a nullary call operator. Take your pick.