Reza
Reza

Reputation: 3919

Using boost::function with templates

I have a problem with boost::function along with template functions. The scenario is as follows;

I want to run a function in another function called "setter". my function is something like

data.totalSize(TotalSize);

totalSize function input argument's type is "uint32_t" and output argument's type is "void".

So I decide to use boost::function; Below is my code:

setter(boost::bind(&myIDL::payload::totalSize,boost::ref(data),_1),(TotalSize));

and the setter implementation is

template<typename Outer>
inline void setter(boost::function<void(Outer)> myFunc, Outer myValue)
{
   myFunc(myValue);
}

I will get the following compile error:

error: no matching function for call to setter(boost::_bi::bind_t<void, boost::_mfi::mf1<void,myIDL::payload, unsigned int>, boost::_bi::list2<boost::reference_wrapper<myIDL::payload>, boost::arg<1> > >, quint32&)'

It seems that boost::function does not understand my template type. So I decide to write it as below:

template<typename Outer>
inline void setter(boost::function<void(unit32_t)> myFunc, Outer myValue)
{
   myFunc(myValue);
}

And it works! So I want to know how to solve my problem. Thanks in advance for your helps.

Best Regards, Reza

Upvotes: 1

Views: 210

Answers (1)

Piotr Skotnicki
Piotr Skotnicki

Reputation: 48447

Template argument type deduction only deduces types, it doesn't consider any conversions. Just like the compiler didn't fail to inform you, the result of boost::bind yields a prvalue of some unspeakable type:

boost::_bi::bind_t<void, boost::_mfi::mf1<void,myIDL::payload
                       , unsigned int>
                       , boost::_bi::list2<boost::reference_wrapper<myIDL::payload>
                                         , boost::arg<1> > >

which, clearly, is not the same as:

boost::function<void(Outer)>

That is, type template parameter Outer cannot be deduced from the type of an argument expression. A solution is to accept any function object:

template <typename F, typename Outer>
inline void setter(F myFunc, Outer myValue)
{
   myFunc(myValue);
}

or put Outer in a non-deduced context (and pay the price of type-erasure):

#include <boost/mpl/identity.hpp>

inline void setter(boost::function<void(typename boost::mpl::identity<Outer>::type)> myFunc
                 , Outer myValue)
{
   myFunc(myValue);
}

Upvotes: 2

Related Questions