Boost logo

Boost Users :

Subject: Re: [Boost-users] Delegating to boost::function with arbitrary signature
From: TONGARI J (tongari95_at_[hidden])
Date: 2013-12-14 11:53:27


2013/12/15 Alexander Lamaison <awl03_at_[hidden]>

> TONGARI J <tongari95_at_[hidden]> writes:
>
> > > 2013/12/14 Alexander Lamaison <span dir="ltr"><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'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'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



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