从 boost::bind_t 自动转换为 boost::function
automatic conversion from boost::bind_t to boost::function
我有一个具有以下签名的方法:
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::函数); (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));
现在,正在做
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::function
中采用 boost::_bi::bind_t
,我想知道我必须做些什么才能使这项工作,没有
- 重新实现
boost::function
- 依赖于 C++11 或更高版本(做不到,遗留编译器支持)
- 使用
boost:phoenix
进行函数式编程(本来可以尝试的,但是我们必须支持的boost版本还没有phoenix
。
我害怕将第三个参数的类型添加为附加模板类型名,因为这会破坏保证 action(converter(pmt::pmt_t))
工作所必需的参数列表类型安全,老实说,我宁愿现在处理的代码比以后检查用户的模板化 g++ 错误要多。
问题是 T
出现在 boost::function
模板参数中 register_msg_action
的签名中。然后,如果您没有使用实际的 boost::function
对象调用它,则无法推断出它。如果您明确指定模板参数,它应该可以工作:
register_msg_action<long>(pmt::mp("key"),
pmt::to_long, /* "raw" function long(pmt_t) */
boost::bind(&my_class::void_method_of_long, this, _1)
);
如果您想在使用至少一个普通函数参数时保留推导 T
的选项,您可以选择在其 [=14] 中显式地使 T
不可推导=] 使用:
template <class T>
struct NonDeduced
{
typedef T type;
};
// T has to be specified explicitly at call site
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
boost::function<typename NonDeduced<T>::type (pmt::pmt_t)> converter,
boost::function<void(typename NonDeduced<T>::type)> action)
// T deducible from converter
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
T converter(pmt::pmt_t),
boost::function<void(typename NonDeduced<T>::type)> action)
// T deducible from action
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
boost::function<typename NonDeduced<T>::type (pmt::pmt_t)> converter,
void action(T))
// T deducible from both, must match
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
T converter(pmt::pmt_t),
void action(T))
我有一个具有以下签名的方法:
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::函数); (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));
现在,正在做
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::function
中采用 boost::_bi::bind_t
,我想知道我必须做些什么才能使这项工作,没有
- 重新实现
boost::function
- 依赖于 C++11 或更高版本(做不到,遗留编译器支持)
- 使用
boost:phoenix
进行函数式编程(本来可以尝试的,但是我们必须支持的boost版本还没有phoenix
。
我害怕将第三个参数的类型添加为附加模板类型名,因为这会破坏保证 action(converter(pmt::pmt_t))
工作所必需的参数列表类型安全,老实说,我宁愿现在处理的代码比以后检查用户的模板化 g++ 错误要多。
问题是 T
出现在 boost::function
模板参数中 register_msg_action
的签名中。然后,如果您没有使用实际的 boost::function
对象调用它,则无法推断出它。如果您明确指定模板参数,它应该可以工作:
register_msg_action<long>(pmt::mp("key"),
pmt::to_long, /* "raw" function long(pmt_t) */
boost::bind(&my_class::void_method_of_long, this, _1)
);
如果您想在使用至少一个普通函数参数时保留推导 T
的选项,您可以选择在其 [=14] 中显式地使 T
不可推导=] 使用:
template <class T>
struct NonDeduced
{
typedef T type;
};
// T has to be specified explicitly at call site
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
boost::function<typename NonDeduced<T>::type (pmt::pmt_t)> converter,
boost::function<void(typename NonDeduced<T>::type)> action)
// T deducible from converter
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
T converter(pmt::pmt_t),
boost::function<void(typename NonDeduced<T>::type)> action)
// T deducible from action
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
boost::function<typename NonDeduced<T>::type (pmt::pmt_t)> converter,
void action(T))
// T deducible from both, must match
template<typename T>
void
register_msg_action(const pmt::pmt_t& name,
T converter(pmt::pmt_t),
void action(T))