У меня есть метод следующей подписи:
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
- это полный тип, прежде чем вы спросите)
а также перегрузки, которые принимают T converter(pmt::pmt_t)
и void converter(T)
(т. е. необработанные функции C/C++), а также все перестановки вышеупомянутых boost::function<>
и аргументы функций в стиле C. Это оставляет мне уже 4 разных метода.
Я хотел бы избежать дальнейшего увеличения количества методов. Однако чаще всего я вызываю что-то вроде
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 */
);
Мой подход заключался в том, что аргумент /* CAVEAT */
неявно преобразуется в boost::function<void(T)>
, но, похоже, это не так (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));
... все остальные кандидаты (boost::function,boost::function); (T(pmt_t),boost::function); (T(pmt_t), пустота(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));
Теперь, делая
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);
прекрасно работает. Поскольку есть даже конструктор, который принимает boost::_bi::bind_t
в boost::function
, мне интересно, что я должен сделать, чтобы это заработало, без
- повторная реализация
boost::function
- полагаясь на С++ 11 или более позднюю версию (не может, поддержка устаревшего компилятора)
- используя
boost:phoenix
для функционального программирования (попробовал бы это, но версии boost, которые мы должны поддерживать, еще не все имеютphoenix
.
Я боюсь добавлять тип третьего аргумента в качестве дополнительного имени типа шаблона, потому что это нарушит безопасность типа списка параметров, которая необходима для гарантии работы action(converter(pmt::pmt_t))
, и, честно говоря, я бы предпочел сейчас иметь дело с большим количеством кода, чем проверять пользовательский шаблон. ошибки g++ позже.