我最近在使用 boost::bind 时遇到代码错误.
来自 boost::bind 文档:
The arguments that bind takes are copied and held internally by the returned function object.
我曾假设持有的拷贝类型是基于函数的签名。但是,它实际上是根据传入的值的类型。
在我的例子中,发生了隐式转换,将绑定(bind)表达式中使用的类型转换为函数接收的类型。我期待这种转换发生在绑定(bind)的位置,但是它发生在使用结果函数对象时。
回想起来,当类型不兼容时,使用 boost::bind 会出错,我应该能够弄清楚这一点 only at the call site, not the bind site .
我的问题是: 为什么 boost::bind 以这种方式工作?
- 它似乎给出了更糟糕的编译器错误消息
- 当发生隐式转换并且多次调用仿函数时,效率似乎较低
但考虑到 Boost 的设计有多好,我猜这是有原因的。它的行为是否继承自 std::bind1st/bind2nd?为什么这很难/不可能实现有什么微妙的原因吗?完全不同的东西?
为了验证第二个理论,我写了一个看起来可行的小代码片段,但很可能有 bind 的特性我没有考虑,因为它只是一个片段:
namespace b = boost;
template<class R, class B1, class A1>
b::_bi::bind_t<R, R (*) (B1), typename b::_bi::list_av_1<B1>::type>
mybind(R (*f) (B1), A1 a1)
{
typedef R (*F) (B1);
typedef typename b::_bi::list_av_1<B1>::type list_type;
return b::_bi::bind_t<R, F, list_type> (f, list_type(B1(a1)));
}
struct Convertible
{
Convertible(int a) : b(a) {}
int b;
};
int foo(Convertible bar)
{
return 2+bar.b;
}
void mainFunc()
{
int x = 3;
b::function<int()> funcObj = mybind(foo, x);
printf("val: %d\n", funcObj());
}
最佳答案
因为仿函数可能支持多个重载,这可能会产生不同的行为。即使当您知道所有参数时可以解析此签名(我不知道标准 C++ 是否可以保证此功能) bind
不知道所有参数,因此肯定无法提供.因此,bind
不具备必要的信息。
编辑:只是为了澄清,考虑一下
struct x {
void operator()(int, std::vector<float>);
void operator()(float, std::string);
};
int main() {
auto b = std::bind(x(), 1); // convert or not?
}
即使您反射(reflection)该结构并了解它的重载,仍然无法确定是否需要将 1
转换为 float 。
关于c++ - 为什么 boost::bind 存储传入类型的参数而不是函数期望的类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11255144/