c++ - 从 boost::bind_t 自动转换为 boost::function

标签 c++ implicit-conversion c++03 boost-bind 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::_bi::bind_tboost::function ,我想知道我必须做什么才能完成这项工作,没有

  • 重新实现 boost::function
  • 依赖于 C++11 或更高版本(做不到,遗留编译器支持)
  • 使用boost:phoenix用于函数式编程(会尝试这个,但我们必须支持的提升版本还没有 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 的选项,您可以选择显式地使 T 不可推导它的 boost::function 使用:

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))

[Live example]

关于c++ - 从 boost::bind_t 自动转换为 boost::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32308494/

相关文章:

c++ - 将用户输入的前两个单词按一个空格拆分,然后存储剩余的短语(C++)

c++ - 函数参数隐式转换失败

scala - 如何解决在 Scala 中采用相同输入类型的模糊隐式转换方法?

c++ - C++03 是 C++ 标准的新版本还是只是 C++98 的技术勘误 (TC)?

c++ - 当我调用WSASend()时,所有数据都会被发送吗?

c++ - libpqxx 关闭准备好的语句和结果

c++ - 从表达式 `wchar_t + wchar_t[]` 到 std::wstring 的隐式转换中的垃圾值

c++ - 使用 SFINAE 选择 friend 或基类 c++x03

c++ - 如何将自己与损坏的 API 和库调用隔离开来

c++ - 虚拟函数实现的菱形继承(钻石问题)