I have a method of the following signature:
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
boost::function<T(pmt::pmt_t)> converter,
boost::function<void(T)> action)
(pmt_t
is a complete type, before you ask)
as well as overloads that take T converter(pmt::pmt_t)
and void converter(T)
(i.e. raw C/C++ functions), as well as all permutations of the above boost::function<>
and the C-style function arguments. That leaves me with 4 different methods already.
I'd like to avoid increasing the number of methods further. However, the most common thing I'll do is call something like
register_msg_action(pmt::mp("key"),
pmt::to_long, /* "raw" function long(pmt_t) */
boost::bind(&my_class::void_method_of_long, this, _1) /* CAVEAT */
);
My approach was that the /* CAVEAT */
argument is implicitly convertible to boost::function<void(T)>
, but however, this doesn't seem to be the case (g++ 5.1.1):
error: no matching function for call to ‘register_msg_action(pmt::pmt_t, boost::function<long int(boost::intrusive_ptr<pmt::pmt_base>)>&, boost::_bi::bind_t<void, void (*)(long int), boost::_bi::list1<boost::arg<1> > >)’
register_msg_action(pmt::mp("hi"), long_function, boost::bind(&my_class::void_method_of_long, this ,_1));
... all the other candidates (boost::function,boost::function); (T(pmt_t),boost::function); (T(pmt_t), void(T)) ...
test.cc:56:1: note: candidate: template<class T> void register_msg_action(const pmt_t&, T (*)(pmt::pmt_t), boost::function<void(T)>)
register_msg_action(const pmt::pmt_t& name,
^
test.cc:56:1: note: template argument deduction/substitution failed:
test.cc:80:76: note: ‘boost::_bi::bind_t<void, void (*)(long int), boost::_bi::list1<boost::arg<1> > >’ is not derived from ‘boost::function<void(T)>’
register_msg_action(pmt::mp("key"), pmt::to_long, boost::bind(&my_class::void_method_of_long, this, _1));
Now, doing
boost::function<void(long)> action (boost::bind(&my_class::void_method_of_long, this, _1));
register_msg_action(pmt::mp("key"), pmt::to_long, action);
works beautifully. Since there is even a constructor that takes boost::_bi::bind_t
in boost::function
, I wonder what I must do to make this work, without
- reimplementing
boost::function
- relying on C++11 or later (can't do, legacy compiler support)
- using
boost:phoenix
for functional programming (would have tried this, but the boost versions we must support don't all havephoenix
yet.
I'm afraid of adding the type of the third argument as additional template typename, because that would break the parameter list type safety that is necessary to guarantee action(converter(pmt::pmt_t))
works, and honestly, I'd rather deal with more code now than examine user's templated g++ errors later on.