Boost logo

Boost Users :

Subject: Re: [Boost-users] Delegating to boost::function with arbitrary signature
From: Alexander Lamaison (awl03_at_[hidden])
Date: 2013-12-16 09:10:03


TONGARI J <tongari95_at_[hidden]> writes:

> 2013/12/15 Alexander Lamaison <span dir="ltr"><mailto:awl03_at_[hidden]></span>
> TONGARI J <mailto:tongari95_at_[hidden]> writes:
>
>> > 2013/12/14 Alexander Lamaison <span dir="ltr"><mailto:mailto:awl03_at_[hidden]></span>
>> > I&#39;ve asked this question on Stack Overflow but not found a solution yet:
>> > http://stackoverflow.com/q/20578575/67013.  It&#39;s
>> > Boost.Function/MPL-related so I&#39;ll ask here too.
>> >
>> > I&#39;m trying to create something like a `boost::function`, but with an
>> > extra &#39;smart handle&#39; tucked inside, which controls the lifetime of a
>> > resource the functions needs to execute correctly.
>> >
>> > If I didn&#39;t need the function signature to be completely generic, this
>> > would be easy.  I would just create a functor with the correct
>> > signature, and keep a `boost::function` and the handle as members.
>> >
>> > However, I do need generic signatures.  The code below is as close as
>> > I&#39;ve got but gets a compile error, presumably, because I&#39;m not able to
>> > unpack a list of arguments like this:
>> >
>> >  template<typename Signature>
>> >  class library_function
>> >  {
>> >  public:
>> >      library_function(
>> >          library_handle handle,
>> >          boost::function<result_type(arg1_type, arg2_type)> function)
>> >          :
>> >      m_handle(handle),
>> >      m_function(function)
>> >      {}
>> >
>> >      typename result_type operator()(arg1_type arg1, arg2_type arg2)
>> >      {
>> >          return m_function(arg1, arg2);
>> >      }
>> >
>> >      // I don&#39;t think I can declare the &#39;params&#39; like this ...
>> >      typename boost::function_types::result_type<Signature>::type operator()(
>> >          boost::function_types::parameter_types<Signature> params)
>> >      {
>> >          return m_function(params); // ... nor unpack them like this
>> >      }
>> >
>> >  private:
>> >      boost::function<Signature> m_function;
>> >      library_handle m_library;
>> >  };
>> >
>> > I think `params` is an MPL list, so what I&#39;ve actually done is declare a
>> > call operator with a single MPL-list parameter.  My MPL-foo is not good.
>> > Is there a way to convert the list to a legal definition of multiple
>> > function paramters?
>
>> Why not just derive from boost::function so you get the call operator
>> for free?
>
> I avoided publicly-inheriting from `boost::function` because that&#39;s just
> asking for slicing problems.  Private inheritance seemed like a good
> idea but I then run into a problem passing the resulting object to
> anything expecting a `boost::function`.  Instead of treating as any
> regular callable object, the compiler knows that it inherits from a
> `boost::function` and complains that the conversion is hidden.  Maybe
> there&#39;s some way round this?Another thought is to use boost::function directly, and provide a make function:template<typename Signature>
> boost::function<Signature> make_library_function(shared_ptr<HMODULE> library, Signature* f){    return library_function<Signature>(library, f);} And library_function becomes:
>
>  template<typename Signature>
>  class library_function
>  {
>  public:
>      library_function(
>          shared_ptr<HMODULE> library, Signature* library_funtion)
>          :
>      m_library(library),
>      m_function(library_function)
>      {}
>
>      operator Signature*() const { return m_function; }
>
>
>  private:
>      shared_ptr<HMODULE> m_library;     Signature* m_function;
>  };Note: code not tested

This works well. The key was `operator Signature*()`. Clever idea,
thanks!

I didn't expect it to work because I though `boost::function` would pull
out the `Signature*` via the cooersion operator, and then the
`library_function` would be destroyed before the call was made.
However, this code proves that it has the desired behaviour, so it must
be keeping a copy of the `library_function` instance inside
`boost::function`: http://ideone.com/BZvuk9.

I didn't use`make_library_function` because inferring the signature
from the raw function isn't something I need.

If you would like to add this answer to the Stack Overflow qusetion,
I'll happily give you the brownie points :)

Thanks,

Alex

-- 
Swish - Easy SFTP for Windows Explorer (http://www.swish-sftp.org)

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