Boost logo

Boost Users :

From: Nikolai N Fetissov (nikolai-boost_at_[hidden])
Date: 2008-06-02 10:59:00


>>> i'm facing this problem may be someone on the list do have an elegant
>>> solution
>>>
>>>
>>> class A;
>>> class B;
>>>
>>> class C {
>>> int operator () (A*,B*)
>>> };
>>>
>>> typedef int (*foobar)(A*,B*);
>>> void do_something(foobar cb);
>>>
>>> C obj;
>>> do_something(obj); *ERROR*
>>
>> Object of type C is not convertible to function
>> pointer type foobar.
>>
>>> did try boost::function<int(A*,B*)> ftor = obj;
>>> do_something(ftor); *ERROR*
>>>
>>> compiler generates in both cases the following error messages
>>> cannot convert parameter 2 from 'boost::function<Signature>' to 'int
>>> (__cdecl
>>> *)(A *,B *)'
>>>
>>> with
>>> 1> [
>>> 1> Signature=int (A *, B *)
>>> 1> ]
>>> 1> No user-defined-conversion operator available that can
>>> perform
>>> this
>>> conversion, or the operator cannot be called
>>>
>>>
>>> I can't make the corresponding class B member function static due to
>>> side-effects.
>>> Any clue how to get rid of this?
>>
>> You got it backwards - raw function pointer is convertible
>> to boost::function, not the other way around (compiler is
>> trying to tell you exactly that.)
>> Make 'do_something' take boost::function instead.
>>
>
> The problem is that "do_something" is a legacy code written in plain C and
> it
> expect to get a function pointer with the signature
>
> typedef int (*foobar)(A*,B*);
> where A and B are struct.
>
> Making the member function that has that signature static helps solve the
> problem but then we do have undesirable side-effect since this operation
> should
> be instance based and not object-bases.
> May be someone can come out with a better approach?!

With such restriction I would go with making C a singleton
(or pooled object - same idea) and doing something like:

  class C {
  public:
    int DoStuff( A*, B* ); // or op() - doesn't matter
    static C& GetInstance( /*XXX*/ ); // or pointer
  private:
    // singleton stuff ...
  };

  // extern "C" ?
  int CallbackFunc( A* a, B* b ) {
    return C::GetInstance( /*XXX*/ ).DoStuff( a, b );
  }

  do_something( CallbackFunc );

This is of course just one way of doing things and very
much depends on the context. Generally, you got a
subsystem boundary and need to figure out a clean interface.

Hope this helps.

--
 Nikolai

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net